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