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 "mirror/class.h" 25#include "method_verifier.h" 26#include "verifier_deps.h" 27 28namespace art { 29namespace verifier { 30 31inline 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 47inline bool RegType::CanAccessMember(ObjPtr<mirror::Class> klass, uint32_t access_flags) const { 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 58inline 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 67inline bool RegType::AssignableFrom(const RegType& lhs, 68 const RegType& rhs, 69 bool strict, 70 MethodVerifier* verifier) { 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(); 90 } else if (lhs.IsConflict()) { 91 LOG(WARNING) << "RegType::AssignableFrom lhs is Conflict!"; 92 return false; 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. 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; 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[] 112 } else if (lhs.HasClass() && rhs.HasClass()) { 113 // Test assignability from the Class point-of-view. 114 bool result = lhs.GetClass()->IsAssignableFrom(rhs.GetClass()); 115 // Record assignability dependency. The `verifier` is null during unit tests and 116 // VerifiedMethod::GenerateSafeCastSet. 117 if (verifier != nullptr) { 118 VerifierDeps::MaybeRecordAssignability( 119 verifier->GetDexFile(), lhs.GetClass(), rhs.GetClass(), strict, result); 120 } 121 return result; 122 } else { 123 // Unresolved types are only assignable for null and equality. 124 return false; 125 } 126 } 127 } 128} 129 130inline bool RegType::IsAssignableFrom(const RegType& src, MethodVerifier* verifier) const { 131 return AssignableFrom(*this, src, false, verifier); 132} 133 134inline bool RegType::IsStrictlyAssignableFrom(const RegType& src, MethodVerifier* verifier) const { 135 return AssignableFrom(*this, src, true, verifier); 136} 137 138inline const DoubleHiType* DoubleHiType::GetInstance() { 139 DCHECK(instance_ != nullptr); 140 return instance_; 141} 142 143inline const DoubleLoType* DoubleLoType::GetInstance() { 144 DCHECK(instance_ != nullptr); 145 return instance_; 146} 147 148inline const LongHiType* LongHiType::GetInstance() { 149 DCHECK(instance_ != nullptr); 150 return instance_; 151} 152 153inline const LongLoType* LongLoType::GetInstance() { 154 DCHECK(instance_ != nullptr); 155 return instance_; 156} 157 158inline const FloatType* FloatType::GetInstance() { 159 DCHECK(instance_ != nullptr); 160 return instance_; 161} 162 163inline const CharType* CharType::GetInstance() { 164 DCHECK(instance_ != nullptr); 165 return instance_; 166} 167 168inline const ShortType* ShortType::GetInstance() { 169 DCHECK(instance_ != nullptr); 170 return instance_; 171} 172 173inline const ByteType* ByteType::GetInstance() { 174 DCHECK(instance_ != nullptr); 175 return instance_; 176} 177 178 179inline const IntegerType* IntegerType::GetInstance() { 180 DCHECK(instance_ != nullptr); 181 return instance_; 182} 183 184inline const BooleanType* BooleanType::GetInstance() { 185 DCHECK(BooleanType::instance_ != nullptr); 186 return BooleanType::instance_; 187} 188 189inline const ConflictType* ConflictType::GetInstance() { 190 DCHECK(instance_ != nullptr); 191 return instance_; 192} 193 194inline const UndefinedType* UndefinedType::GetInstance() { 195 DCHECK(instance_ != nullptr); 196 return instance_; 197} 198 199inline void* RegType::operator new(size_t size, ScopedArenaAllocator* arena) { 200 return arena->Alloc(size, kArenaAllocMisc); 201} 202 203} // namespace verifier 204} // namespace art 205 206#endif // ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_ 207