Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 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/casts.h" |
Mathieu Chartier | de40d47 | 2015-10-15 17:47:48 -0700 | [diff] [blame] | 23 | #include "base/scoped_arena_allocator.h" |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 24 | #include "mirror/class.h" |
David Brazdil | ca3c8c3 | 2016-09-06 14:04:48 +0100 | [diff] [blame] | 25 | #include "method_verifier.h" |
| 26 | #include "verifier_deps.h" |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 27 | |
| 28 | namespace art { |
| 29 | namespace verifier { |
| 30 | |
| 31 | inline bool RegType::CanAccess(const RegType& other) const { |
| 32 | if (Equals(other)) { |
| 33 | return true; // Trivial accessibility. |
| 34 | } else { |
| 35 | bool this_unresolved = IsUnresolvedTypes(); |
| 36 | bool other_unresolved = other.IsUnresolvedTypes(); |
| 37 | if (!this_unresolved && !other_unresolved) { |
| 38 | return GetClass()->CanAccess(other.GetClass()); |
| 39 | } else if (!other_unresolved) { |
| 40 | return other.GetClass()->IsPublic(); // Be conservative, only allow if other is public. |
| 41 | } else { |
| 42 | return false; // More complicated test not possible on unresolved types, be conservative. |
| 43 | } |
| 44 | } |
| 45 | } |
| 46 | |
Mathieu Chartier | 3398c78 | 2016-09-30 10:27:43 -0700 | [diff] [blame] | 47 | inline bool RegType::CanAccessMember(ObjPtr<mirror::Class> klass, uint32_t access_flags) const { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 48 | if ((access_flags & kAccPublic) != 0) { |
| 49 | return true; |
| 50 | } |
| 51 | if (!IsUnresolvedTypes()) { |
| 52 | return GetClass()->CanAccessMember(klass, access_flags); |
| 53 | } else { |
| 54 | return false; // More complicated test not possible on unresolved types, be conservative. |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | inline bool RegType::IsConstantBoolean() const { |
| 59 | if (!IsConstant()) { |
| 60 | return false; |
| 61 | } else { |
| 62 | const ConstantType* const_val = down_cast<const ConstantType*>(this); |
| 63 | return const_val->ConstantValue() >= 0 && const_val->ConstantValue() <= 1; |
| 64 | } |
| 65 | } |
| 66 | |
David Brazdil | ca3c8c3 | 2016-09-06 14:04:48 +0100 | [diff] [blame] | 67 | inline bool RegType::AssignableFrom(const RegType& lhs, |
| 68 | const RegType& rhs, |
| 69 | bool strict, |
| 70 | MethodVerifier* verifier) { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 71 | if (lhs.Equals(rhs)) { |
| 72 | return true; |
| 73 | } else { |
| 74 | if (lhs.IsBoolean()) { |
| 75 | return rhs.IsBooleanTypes(); |
| 76 | } else if (lhs.IsByte()) { |
| 77 | return rhs.IsByteTypes(); |
| 78 | } else if (lhs.IsShort()) { |
| 79 | return rhs.IsShortTypes(); |
| 80 | } else if (lhs.IsChar()) { |
| 81 | return rhs.IsCharTypes(); |
| 82 | } else if (lhs.IsInteger()) { |
| 83 | return rhs.IsIntegralTypes(); |
| 84 | } else if (lhs.IsFloat()) { |
| 85 | return rhs.IsFloatTypes(); |
| 86 | } else if (lhs.IsLongLo()) { |
| 87 | return rhs.IsLongTypes(); |
| 88 | } else if (lhs.IsDoubleLo()) { |
| 89 | return rhs.IsDoubleTypes(); |
Stephen Kyle | 40d3518 | 2014-10-03 13:47:56 +0100 | [diff] [blame] | 90 | } else if (lhs.IsConflict()) { |
| 91 | LOG(WARNING) << "RegType::AssignableFrom lhs is Conflict!"; |
| 92 | return false; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 93 | } else { |
| 94 | CHECK(lhs.IsReferenceTypes()) |
| 95 | << "Unexpected register type in IsAssignableFrom: '" |
| 96 | << lhs << "' := '" << rhs << "'"; |
| 97 | if (rhs.IsZero()) { |
| 98 | return true; // All reference types can be assigned null. |
| 99 | } else if (!rhs.IsReferenceTypes()) { |
| 100 | return false; // Expect rhs to be a reference type. |
David Brazdil | 68b5c0b | 2016-01-19 14:25:29 +0000 | [diff] [blame] | 101 | } else if (lhs.IsUninitializedTypes() || rhs.IsUninitializedTypes()) { |
| 102 | // Uninitialized types are only allowed to be assigned to themselves. |
| 103 | // TODO: Once we have a proper "reference" super type, this needs to be extended. |
| 104 | return false; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 105 | } else if (lhs.IsJavaLangObject()) { |
| 106 | return true; // All reference types can be assigned to Object. |
| 107 | } else if (!strict && !lhs.IsUnresolvedTypes() && lhs.GetClass()->IsInterface()) { |
| 108 | // If we're not strict allow assignment to any interface, see comment in ClassJoin. |
| 109 | return true; |
| 110 | } else if (lhs.IsJavaLangObjectArray()) { |
| 111 | return rhs.IsObjectArrayTypes(); // All reference arrays may be assigned to Object[] |
David Brazdil | ca3c8c3 | 2016-09-06 14:04:48 +0100 | [diff] [blame] | 112 | } else if (lhs.HasClass() && rhs.HasClass()) { |
| 113 | // Test assignability from the Class point-of-view. |
| 114 | bool result = lhs.GetClass()->IsAssignableFrom(rhs.GetClass()); |
Nicolas Geoffray | 119e846 | 2016-12-21 10:29:43 +0000 | [diff] [blame^] | 115 | // Record assignability dependency. The `verifier` is null during unit tests and |
| 116 | // VerifiedMethod::GenerateSafeCastSet. |
David Brazdil | ca3c8c3 | 2016-09-06 14:04:48 +0100 | [diff] [blame] | 117 | if (verifier != nullptr) { |
| 118 | VerifierDeps::MaybeRecordAssignability( |
| 119 | verifier->GetDexFile(), lhs.GetClass(), rhs.GetClass(), strict, result); |
| 120 | } |
| 121 | return result; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 122 | } else { |
| 123 | // Unresolved types are only assignable for null and equality. |
| 124 | return false; |
| 125 | } |
| 126 | } |
| 127 | } |
| 128 | } |
| 129 | |
David Brazdil | ca3c8c3 | 2016-09-06 14:04:48 +0100 | [diff] [blame] | 130 | inline bool RegType::IsAssignableFrom(const RegType& src, MethodVerifier* verifier) const { |
| 131 | return AssignableFrom(*this, src, false, verifier); |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 132 | } |
| 133 | |
David Brazdil | ca3c8c3 | 2016-09-06 14:04:48 +0100 | [diff] [blame] | 134 | inline bool RegType::IsStrictlyAssignableFrom(const RegType& src, MethodVerifier* verifier) const { |
| 135 | return AssignableFrom(*this, src, true, verifier); |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 136 | } |
| 137 | |
| 138 | inline const DoubleHiType* DoubleHiType::GetInstance() { |
| 139 | DCHECK(instance_ != nullptr); |
| 140 | return instance_; |
| 141 | } |
| 142 | |
| 143 | inline const DoubleLoType* DoubleLoType::GetInstance() { |
| 144 | DCHECK(instance_ != nullptr); |
| 145 | return instance_; |
| 146 | } |
| 147 | |
| 148 | inline const LongHiType* LongHiType::GetInstance() { |
| 149 | DCHECK(instance_ != nullptr); |
| 150 | return instance_; |
| 151 | } |
| 152 | |
| 153 | inline const LongLoType* LongLoType::GetInstance() { |
| 154 | DCHECK(instance_ != nullptr); |
| 155 | return instance_; |
| 156 | } |
| 157 | |
| 158 | inline const FloatType* FloatType::GetInstance() { |
| 159 | DCHECK(instance_ != nullptr); |
| 160 | return instance_; |
| 161 | } |
| 162 | |
| 163 | inline const CharType* CharType::GetInstance() { |
| 164 | DCHECK(instance_ != nullptr); |
| 165 | return instance_; |
| 166 | } |
| 167 | |
| 168 | inline const ShortType* ShortType::GetInstance() { |
| 169 | DCHECK(instance_ != nullptr); |
| 170 | return instance_; |
| 171 | } |
| 172 | |
| 173 | inline const ByteType* ByteType::GetInstance() { |
| 174 | DCHECK(instance_ != nullptr); |
| 175 | return instance_; |
| 176 | } |
| 177 | |
| 178 | |
| 179 | inline const IntegerType* IntegerType::GetInstance() { |
| 180 | DCHECK(instance_ != nullptr); |
| 181 | return instance_; |
| 182 | } |
| 183 | |
| 184 | inline const BooleanType* BooleanType::GetInstance() { |
| 185 | DCHECK(BooleanType::instance_ != nullptr); |
| 186 | return BooleanType::instance_; |
| 187 | } |
| 188 | |
| 189 | inline const ConflictType* ConflictType::GetInstance() { |
| 190 | DCHECK(instance_ != nullptr); |
| 191 | return instance_; |
| 192 | } |
| 193 | |
| 194 | inline const UndefinedType* UndefinedType::GetInstance() { |
| 195 | DCHECK(instance_ != nullptr); |
| 196 | return instance_; |
| 197 | } |
| 198 | |
Mathieu Chartier | de40d47 | 2015-10-15 17:47:48 -0700 | [diff] [blame] | 199 | inline void* RegType::operator new(size_t size, ScopedArenaAllocator* arena) { |
| 200 | return arena->Alloc(size, kArenaAllocMisc); |
| 201 | } |
| 202 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 203 | } // namespace verifier |
| 204 | } // namespace art |
| 205 | |
| 206 | #endif // ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_ |