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 && result) { 119 VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(), 120 verifier->GetDexFile(), 121 verifier->GetClassDef(), 122 lhs.GetClass(), 123 rhs.GetClass()); 124 } 125 return result; 126 } else { 127 // For unresolved types, we don't know if they are assignable, and the 128 // verifier will continue assuming they are. We need to record that. 129 if (verifier != nullptr) { 130 VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(), 131 verifier->GetDexFile(), 132 verifier->GetClassDef(), 133 lhs, 134 rhs); 135 } 136 // Unresolved types are only assignable for null and equality. 137 // Null cannot be the left-hand side. 138 return false; 139 } 140 case AssignmentType::kNotAssignable: 141 break; 142 } 143 LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '" 144 << lhs << "' := '" << rhs << "'"; 145 UNREACHABLE(); 146 } 147 } 148 149 inline bool RegType::IsAssignableFrom(const RegType& src, MethodVerifier* verifier) const { 150 return AssignableFrom(*this, src, false, verifier); 151 } 152 153 inline bool RegType::IsStrictlyAssignableFrom(const RegType& src, MethodVerifier* verifier) const { 154 return AssignableFrom(*this, src, true, verifier); 155 } 156 157 inline const DoubleHiType* DoubleHiType::GetInstance() { 158 DCHECK(instance_ != nullptr); 159 return instance_; 160 } 161 162 inline const DoubleLoType* DoubleLoType::GetInstance() { 163 DCHECK(instance_ != nullptr); 164 return instance_; 165 } 166 167 inline const LongHiType* LongHiType::GetInstance() { 168 DCHECK(instance_ != nullptr); 169 return instance_; 170 } 171 172 inline const LongLoType* LongLoType::GetInstance() { 173 DCHECK(instance_ != nullptr); 174 return instance_; 175 } 176 177 inline const FloatType* FloatType::GetInstance() { 178 DCHECK(instance_ != nullptr); 179 return instance_; 180 } 181 182 inline const CharType* CharType::GetInstance() { 183 DCHECK(instance_ != nullptr); 184 return instance_; 185 } 186 187 inline const ShortType* ShortType::GetInstance() { 188 DCHECK(instance_ != nullptr); 189 return instance_; 190 } 191 192 inline const ByteType* ByteType::GetInstance() { 193 DCHECK(instance_ != nullptr); 194 return instance_; 195 } 196 197 198 inline const IntegerType* IntegerType::GetInstance() { 199 DCHECK(instance_ != nullptr); 200 return instance_; 201 } 202 203 inline const BooleanType* BooleanType::GetInstance() { 204 DCHECK(BooleanType::instance_ != nullptr); 205 return BooleanType::instance_; 206 } 207 208 inline const ConflictType* ConflictType::GetInstance() { 209 DCHECK(instance_ != nullptr); 210 return instance_; 211 } 212 213 inline const UndefinedType* UndefinedType::GetInstance() { 214 DCHECK(instance_ != nullptr); 215 return instance_; 216 } 217 218 inline const NullType* NullType::GetInstance() { 219 DCHECK(instance_ != nullptr); 220 return instance_; 221 } 222 223 inline void* RegType::operator new(size_t size, ScopedArenaAllocator* allocator) { 224 return allocator->Alloc(size, kArenaAllocMisc); 225 } 226 227 } // namespace verifier 228 } // namespace art 229 230 #endif // ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_ 231