1 /* 2 * Copyright (C) 2013 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_REGISTER_LINE_INL_H_ 18 #define ART_RUNTIME_VERIFIER_REGISTER_LINE_INL_H_ 19 20 #include "register_line.h" 21 22 #include "method_verifier.h" 23 #include "reg_type_cache-inl.h" 24 25 namespace art { 26 namespace verifier { 27 28 inline const RegType& RegisterLine::GetRegisterType(MethodVerifier* verifier, uint32_t vsrc) const { 29 // The register index was validated during the static pass, so we don't need to check it here. 30 DCHECK_LT(vsrc, num_regs_); 31 return verifier->GetRegTypeCache()->GetFromId(line_[vsrc]); 32 } 33 34 inline bool RegisterLine::SetRegisterType(MethodVerifier* verifier, uint32_t vdst, 35 const RegType& new_type) { 36 DCHECK_LT(vdst, num_regs_); 37 if (new_type.IsLowHalf() || new_type.IsHighHalf()) { 38 verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Expected category1 register type not '" 39 << new_type << "'"; 40 return false; 41 } else { 42 // Note: previously we failed when asked to set a conflict. However, conflicts are OK as long 43 // as they are not accessed, and our backends can handle this nowadays. 44 line_[vdst] = new_type.GetId(); 45 } 46 // Clear the monitor entry bits for this register. 47 ClearAllRegToLockDepths(vdst); 48 return true; 49 } 50 51 inline bool RegisterLine::SetRegisterTypeWide(MethodVerifier* verifier, uint32_t vdst, 52 const RegType& new_type1, 53 const RegType& new_type2) { 54 DCHECK_LT(vdst + 1, num_regs_); 55 if (!new_type1.CheckWidePair(new_type2)) { 56 verifier->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Invalid wide pair '" 57 << new_type1 << "' '" << new_type2 << "'"; 58 return false; 59 } else { 60 line_[vdst] = new_type1.GetId(); 61 line_[vdst + 1] = new_type2.GetId(); 62 } 63 // Clear the monitor entry bits for this register. 64 ClearAllRegToLockDepths(vdst); 65 ClearAllRegToLockDepths(vdst + 1); 66 return true; 67 } 68 69 inline void RegisterLine::SetResultTypeToUnknown(MethodVerifier* verifier) { 70 result_[0] = verifier->GetRegTypeCache()->Undefined().GetId(); 71 result_[1] = result_[0]; 72 } 73 74 inline void RegisterLine::SetResultRegisterType(MethodVerifier* verifier, const RegType& new_type) { 75 DCHECK(!new_type.IsLowHalf()); 76 DCHECK(!new_type.IsHighHalf()); 77 result_[0] = new_type.GetId(); 78 result_[1] = verifier->GetRegTypeCache()->Undefined().GetId(); 79 } 80 81 inline void RegisterLine::SetResultRegisterTypeWide(const RegType& new_type1, 82 const RegType& new_type2) { 83 DCHECK(new_type1.CheckWidePair(new_type2)); 84 result_[0] = new_type1.GetId(); 85 result_[1] = new_type2.GetId(); 86 } 87 88 inline void RegisterLine::CopyRegister1(MethodVerifier* verifier, uint32_t vdst, uint32_t vsrc, 89 TypeCategory cat) { 90 DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef); 91 const RegType& type = GetRegisterType(verifier, vsrc); 92 if (!SetRegisterType(verifier, vdst, type)) { 93 return; 94 } 95 if (!type.IsConflict() && // Allow conflicts to be copied around. 96 ((cat == kTypeCategory1nr && !type.IsCategory1Types()) || 97 (cat == kTypeCategoryRef && !type.IsReferenceTypes()))) { 98 verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy1 v" << vdst << "<-v" << vsrc << " type=" << type 99 << " cat=" << static_cast<int>(cat); 100 } else if (cat == kTypeCategoryRef) { 101 CopyRegToLockDepth(vdst, vsrc); 102 } 103 } 104 105 inline void RegisterLine::CopyRegister2(MethodVerifier* verifier, uint32_t vdst, uint32_t vsrc) { 106 const RegType& type_l = GetRegisterType(verifier, vsrc); 107 const RegType& type_h = GetRegisterType(verifier, vsrc + 1); 108 109 if (!type_l.CheckWidePair(type_h)) { 110 verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy2 v" << vdst << "<-v" << vsrc 111 << " type=" << type_l << "/" << type_h; 112 } else { 113 SetRegisterTypeWide(verifier, vdst, type_l, type_h); 114 } 115 } 116 117 inline size_t RegisterLine::GetMaxNonZeroReferenceReg(MethodVerifier* verifier, 118 size_t max_ref_reg) const { 119 size_t i = static_cast<int>(max_ref_reg) < 0 ? 0 : max_ref_reg; 120 for (; i < num_regs_; i++) { 121 if (GetRegisterType(verifier, i).IsNonZeroReferenceTypes()) { 122 max_ref_reg = i; 123 } 124 } 125 return max_ref_reg; 126 } 127 128 inline bool RegisterLine::VerifyRegisterType(MethodVerifier* verifier, uint32_t vsrc, 129 const RegType& check_type) { 130 // Verify the src register type against the check type refining the type of the register 131 const RegType& src_type = GetRegisterType(verifier, vsrc); 132 if (UNLIKELY(!check_type.IsAssignableFrom(src_type))) { 133 enum VerifyError fail_type; 134 if (!check_type.IsNonZeroReferenceTypes() || !src_type.IsNonZeroReferenceTypes()) { 135 // Hard fail if one of the types is primitive, since they are concretely known. 136 fail_type = VERIFY_ERROR_BAD_CLASS_HARD; 137 } else if (check_type.IsUnresolvedTypes() || src_type.IsUnresolvedTypes()) { 138 fail_type = VERIFY_ERROR_NO_CLASS; 139 } else { 140 fail_type = VERIFY_ERROR_BAD_CLASS_SOFT; 141 } 142 verifier->Fail(fail_type) << "register v" << vsrc << " has type " 143 << src_type << " but expected " << check_type; 144 return false; 145 } 146 if (check_type.IsLowHalf()) { 147 const RegType& src_type_h = GetRegisterType(verifier, vsrc + 1); 148 if (UNLIKELY(!src_type.CheckWidePair(src_type_h))) { 149 verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "wide register v" << vsrc << " has type " 150 << src_type << "/" << src_type_h; 151 return false; 152 } 153 } 154 // The register at vsrc has a defined type, we know the lower-upper-bound, but this is less 155 // precise than the subtype in vsrc so leave it for reference types. For primitive types 156 // if they are a defined type then they are as precise as we can get, however, for constant 157 // types we may wish to refine them. Unfortunately constant propagation has rendered this useless. 158 return true; 159 } 160 161 inline bool RegisterLine::VerifyMonitorStackEmpty(MethodVerifier* verifier) const { 162 if (MonitorStackDepth() != 0) { 163 verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected empty monitor stack"; 164 return false; 165 } else { 166 return true; 167 } 168 } 169 170 } // namespace verifier 171 } // namespace art 172 173 #endif // ART_RUNTIME_VERIFIER_REGISTER_LINE_INL_H_ 174