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