diff options
Diffstat (limited to 'runtime/verifier/method_verifier.cc')
-rw-r--r-- | runtime/verifier/method_verifier.cc | 419 |
1 files changed, 221 insertions, 198 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index a18b00e66d..ede8e366d7 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -708,6 +708,39 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { } } + NO_INLINE void FailForRegisterType(uint32_t vsrc, + const RegType& check_type, + const RegType& src_type, + VerifyError fail_type = VERIFY_ERROR_BAD_CLASS_HARD) + REQUIRES_SHARED(Locks::mutator_lock_) { + Fail(fail_type) + << "register v" << vsrc << " has type " << src_type << " but expected " << check_type; + } + + NO_INLINE void FailForRegisterType(uint32_t vsrc, + RegType::Kind check_kind, + uint16_t src_type_id) + REQUIRES_SHARED(Locks::mutator_lock_) { + FailForRegisterType( + vsrc, reg_types_.GetFromRegKind(check_kind), reg_types_.GetFromId(src_type_id)); + } + + NO_INLINE void FailForRegisterTypeWide(uint32_t vsrc, + const RegType& src_type, + const RegType& src_type_h) + REQUIRES_SHARED(Locks::mutator_lock_) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) + << "wide register v" << vsrc << " has type " << src_type << "/" << src_type_h; + } + + NO_INLINE void FailForRegisterTypeWide(uint32_t vsrc, + uint16_t src_type_id, + uint16_t src_type_id_h) + REQUIRES_SHARED(Locks::mutator_lock_) { + FailForRegisterTypeWide( + vsrc, reg_types_.GetFromId(src_type_id), reg_types_.GetFromId(src_type_id_h)); + } + ALWAYS_INLINE inline bool VerifyRegisterType(uint32_t vsrc, const RegType& check_type) REQUIRES_SHARED(Locks::mutator_lock_) { // Verify the src register type against the check type refining the type of the register @@ -725,15 +758,13 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { } else { fail_type = VERIFY_ERROR_BAD_CLASS_HARD; } - Fail(fail_type) << "register v" << vsrc << " has type " - << src_type << " but expected " << check_type; + FailForRegisterType(vsrc, check_type, src_type, fail_type); return false; } if (check_type.IsLowHalf()) { const RegType& src_type_h = work_line_->GetRegisterType(this, vsrc + 1); if (UNLIKELY(!src_type.CheckWidePair(src_type_h))) { - Fail(VERIFY_ERROR_BAD_CLASS_HARD) - << "wide register v" << vsrc << " has type " << src_type << "/" << src_type_h; + FailForRegisterTypeWide(vsrc, src_type, src_type_h); return false; } } @@ -744,22 +775,46 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { return true; } - bool VerifyRegisterTypeWide(uint32_t vsrc, - const RegType& check_type1, - const RegType& check_type2) + ALWAYS_INLINE inline bool VerifyRegisterType(uint32_t vsrc, RegType::Kind check_kind) REQUIRES_SHARED(Locks::mutator_lock_) { - DCHECK(check_type1.CheckWidePair(check_type2)); + DCHECK(check_kind == RegType::Kind::kInteger || check_kind == RegType::Kind::kFloat); // Verify the src register type against the check type refining the type of the register - const RegType& src_type = work_line_->GetRegisterType(this, vsrc); - if (!check_type1.IsAssignableFrom(src_type, this)) { - Fail(VERIFY_ERROR_BAD_CLASS_HARD) - << "register v" << vsrc << " has type " << src_type << " but expected " << check_type1; + uint16_t src_type_id = work_line_->GetRegisterTypeId(vsrc); + if (UNLIKELY(src_type_id >= RegTypeCache::NumberOfRegKindCacheIds()) || + UNLIKELY(RegType::AssignabilityFrom(check_kind, RegTypeCache::RegKindForId(src_type_id)) != + RegType::Assignability::kAssignable)) { + // Integer or float assignability is never a `kNarrowingConversion` or `kReference`. + DCHECK_EQ( + RegType::AssignabilityFrom(check_kind, reg_types_.GetFromId(src_type_id).GetKind()), + RegType::Assignability::kNotAssignable); + FailForRegisterType(vsrc, check_kind, src_type_id); return false; } - const RegType& src_type_h = work_line_->GetRegisterType(this, vsrc + 1); - if (!src_type.CheckWidePair(src_type_h)) { - Fail(VERIFY_ERROR_BAD_CLASS_HARD) - << "wide register v" << vsrc << " has type " << src_type << "/" << src_type_h; + return true; + } + + bool VerifyRegisterTypeWide(uint32_t vsrc, RegType::Kind check_kind) + REQUIRES_SHARED(Locks::mutator_lock_) { + DCHECK(check_kind == RegType::Kind::kLongLo || check_kind == RegType::Kind::kDoubleLo); + // Verify the src register type against the check type refining the type of the register + uint16_t src_type_id = work_line_->GetRegisterTypeId(vsrc); + if (UNLIKELY(src_type_id >= RegTypeCache::NumberOfRegKindCacheIds()) || + UNLIKELY(RegType::AssignabilityFrom(check_kind, RegTypeCache::RegKindForId(src_type_id)) != + RegType::Assignability::kAssignable)) { + // Wide assignability is never a `kNarrowingConversion` or `kReference`. + DCHECK_EQ( + RegType::AssignabilityFrom(check_kind, reg_types_.GetFromId(src_type_id).GetKind()), + RegType::Assignability::kNotAssignable); + FailForRegisterType(vsrc, check_kind, src_type_id); + return false; + } + uint16_t src_type_id_h = work_line_->GetRegisterTypeId(vsrc + 1); + uint16_t expected_src_type_id_h = + RegTypeCache::IdForRegKind(RegType::ToHighHalf(RegTypeCache::RegKindForId(src_type_id))); + DCHECK_EQ(src_type_id_h == expected_src_type_id_h, + reg_types_.GetFromId(src_type_id).CheckWidePair(reg_types_.GetFromId(src_type_id_h))); + if (UNLIKELY(src_type_id_h != expected_src_type_id_h)) { + FailForRegisterTypeWide(vsrc, src_type_id, src_type_id_h); return false; } // The register at vsrc has a defined type, we know the lower-upper-bound, but this is less @@ -773,41 +828,37 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { * Verify types for a simple two-register instruction (e.g. "neg-int"). * "dst_type" is stored into vA, and "src_type" is verified against vB. */ - void CheckUnaryOp(const Instruction* inst, const RegType& dst_type, const RegType& src_type) + void CheckUnaryOp(const Instruction* inst, RegType::Kind dst_kind, RegType::Kind src_kind) REQUIRES_SHARED(Locks::mutator_lock_) { - if (VerifyRegisterType(inst->VRegB_12x(), src_type)) { - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_12x(), dst_type); + if (VerifyRegisterType(inst->VRegB_12x(), src_kind)) { + work_line_->SetRegisterType(inst->VRegA_12x(), dst_kind); } } void CheckUnaryOpWide(const Instruction* inst, - const RegType& dst_type1, - const RegType& dst_type2, - const RegType& src_type1, - const RegType& src_type2) + RegType::Kind dst_kind, + RegType::Kind src_kind) REQUIRES_SHARED(Locks::mutator_lock_) { - if (VerifyRegisterTypeWide(inst->VRegB_12x(), src_type1, src_type2)) { - work_line_->SetRegisterTypeWide(inst->VRegA_12x(), dst_type1, dst_type2); + if (VerifyRegisterTypeWide(inst->VRegB_12x(), src_kind)) { + work_line_->SetRegisterTypeWide(inst->VRegA_12x(), dst_kind, RegType::ToHighHalf(dst_kind)); } } void CheckUnaryOpToWide(const Instruction* inst, - const RegType& dst_type1, - const RegType& dst_type2, - const RegType& src_type) + RegType::Kind dst_kind, + RegType::Kind src_kind) REQUIRES_SHARED(Locks::mutator_lock_) { - if (VerifyRegisterType(inst->VRegB_12x(), src_type)) { - work_line_->SetRegisterTypeWide(inst->VRegA_12x(), dst_type1, dst_type2); + if (VerifyRegisterType(inst->VRegB_12x(), src_kind)) { + work_line_->SetRegisterTypeWide(inst->VRegA_12x(), dst_kind, RegType::ToHighHalf(dst_kind)); } } void CheckUnaryOpFromWide(const Instruction* inst, - const RegType& dst_type, - const RegType& src_type1, - const RegType& src_type2) + RegType::Kind dst_kind, + RegType::Kind src_kind) REQUIRES_SHARED(Locks::mutator_lock_) { - if (VerifyRegisterTypeWide(inst->VRegB_12x(), src_type1, src_type2)) { - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_12x(), dst_type); + if (VerifyRegisterTypeWide(inst->VRegB_12x(), src_kind)) { + work_line_->SetRegisterType(inst->VRegA_12x(), dst_kind); } } @@ -817,49 +868,60 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { * against vB/vC. */ void CheckBinaryOp(const Instruction* inst, - const RegType& dst_type, - const RegType& src_type1, - const RegType& src_type2, + RegType::Kind dst_kind, + RegType::Kind src_kind1, + RegType::Kind src_kind2, bool check_boolean_op) REQUIRES_SHARED(Locks::mutator_lock_) { + const uint32_t vregA = inst->VRegA_23x(); const uint32_t vregB = inst->VRegB_23x(); const uint32_t vregC = inst->VRegC_23x(); - if (VerifyRegisterType(vregB, src_type1) && - VerifyRegisterType(vregC, src_type2)) { + if (VerifyRegisterType(vregB, src_kind1) && + VerifyRegisterType(vregC, src_kind2)) { if (check_boolean_op) { - DCHECK(dst_type.IsInteger()); - if (work_line_->GetRegisterType(this, vregB).IsBooleanTypes() && - work_line_->GetRegisterType(this, vregC).IsBooleanTypes()) { - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_23x(), reg_types_.Boolean()); + DCHECK_EQ(dst_kind, RegType::Kind::kInteger); + if (RegType::IsBooleanTypes( + RegTypeCache::RegKindForId(work_line_->GetRegisterTypeId(vregB))) && + RegType::IsBooleanTypes( + RegTypeCache::RegKindForId(work_line_->GetRegisterTypeId(vregC)))) { + work_line_->SetRegisterType(vregA, RegType::Kind::kBoolean); return; } } - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_23x(), dst_type); + work_line_->SetRegisterType(vregA, dst_kind); } } void CheckBinaryOpWide(const Instruction* inst, - const RegType& dst_type1, - const RegType& dst_type2, - const RegType& src_type1_1, - const RegType& src_type1_2, - const RegType& src_type2_1, - const RegType& src_type2_2) + RegType::Kind dst_kind, + RegType::Kind src_kind1, + RegType::Kind src_kind2) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (VerifyRegisterTypeWide(inst->VRegB_23x(), src_kind1) && + VerifyRegisterTypeWide(inst->VRegC_23x(), src_kind2)) { + work_line_->SetRegisterTypeWide(inst->VRegA_23x(), dst_kind, RegType::ToHighHalf(dst_kind)); + } + } + + void CheckBinaryOpWideCmp(const Instruction* inst, + RegType::Kind dst_kind, + RegType::Kind src_kind1, + RegType::Kind src_kind2) REQUIRES_SHARED(Locks::mutator_lock_) { - if (VerifyRegisterTypeWide(inst->VRegB_23x(), src_type1_1, src_type1_2) && - VerifyRegisterTypeWide(inst->VRegC_23x(), src_type2_1, src_type2_2)) { - work_line_->SetRegisterTypeWide(inst->VRegA_23x(), dst_type1, dst_type2); + if (VerifyRegisterTypeWide(inst->VRegB_23x(), src_kind1) && + VerifyRegisterTypeWide(inst->VRegC_23x(), src_kind2)) { + work_line_->SetRegisterType(inst->VRegA_23x(), dst_kind); } } void CheckBinaryOpWideShift(const Instruction* inst, - const RegType& long_lo_type, - const RegType& long_hi_type, - const RegType& int_type) + RegType::Kind long_lo_kind, + RegType::Kind int_kind) REQUIRES_SHARED(Locks::mutator_lock_) { - if (VerifyRegisterTypeWide(inst->VRegB_23x(), long_lo_type, long_hi_type) && - VerifyRegisterType(inst->VRegC_23x(), int_type)) { - work_line_->SetRegisterTypeWide(inst->VRegA_23x(), long_lo_type, long_hi_type); + if (VerifyRegisterTypeWide(inst->VRegB_23x(), long_lo_kind) && + VerifyRegisterType(inst->VRegC_23x(), int_kind)) { + RegType::Kind long_hi_kind = RegType::ToHighHalf(long_lo_kind); + work_line_->SetRegisterTypeWide(inst->VRegA_23x(), long_lo_kind, long_hi_kind); } } @@ -868,53 +930,52 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { * are verified against vA/vB, then "dst_type" is stored into vA. */ void CheckBinaryOp2addr(const Instruction* inst, - const RegType& dst_type, - const RegType& src_type1, - const RegType& src_type2, + RegType::Kind dst_kind, + RegType::Kind src_kind1, + RegType::Kind src_kind2, bool check_boolean_op) REQUIRES_SHARED(Locks::mutator_lock_) { const uint32_t vregA = inst->VRegA_12x(); const uint32_t vregB = inst->VRegB_12x(); - if (VerifyRegisterType(vregA, src_type1) && - VerifyRegisterType(vregB, src_type2)) { + if (VerifyRegisterType(vregA, src_kind1) && + VerifyRegisterType(vregB, src_kind2)) { if (check_boolean_op) { - DCHECK(dst_type.IsInteger()); - if (work_line_->GetRegisterType(this, vregA).IsBooleanTypes() && - work_line_->GetRegisterType(this, vregB).IsBooleanTypes()) { - work_line_->SetRegisterType<LockOp::kClear>(vregA, reg_types_.Boolean()); + DCHECK_EQ(dst_kind, RegType::Kind::kInteger); + if (RegType::IsBooleanTypes( + RegTypeCache::RegKindForId(work_line_->GetRegisterTypeId(vregA))) && + RegType::IsBooleanTypes( + RegTypeCache::RegKindForId(work_line_->GetRegisterTypeId(vregB)))) { + work_line_->SetRegisterType(vregA, RegType::Kind::kBoolean); return; } } - work_line_->SetRegisterType<LockOp::kClear>(vregA, dst_type); + work_line_->SetRegisterType(vregA, dst_kind); } } void CheckBinaryOp2addrWide(const Instruction* inst, - const RegType& dst_type1, - const RegType& dst_type2, - const RegType& src_type1_1, - const RegType& src_type1_2, - const RegType& src_type2_1, - const RegType& src_type2_2) + RegType::Kind dst_kind, + RegType::Kind src_kind1, + RegType::Kind src_kind2) REQUIRES_SHARED(Locks::mutator_lock_) { const uint32_t vregA = inst->VRegA_12x(); const uint32_t vregB = inst->VRegB_12x(); - if (VerifyRegisterTypeWide(vregA, src_type1_1, src_type1_2) && - VerifyRegisterTypeWide(vregB, src_type2_1, src_type2_2)) { - work_line_->SetRegisterTypeWide(vregA, dst_type1, dst_type2); + if (VerifyRegisterTypeWide(vregA, src_kind1) && + VerifyRegisterTypeWide(vregB, src_kind2)) { + work_line_->SetRegisterTypeWide(vregA, dst_kind, RegType::ToHighHalf(dst_kind)); } } void CheckBinaryOp2addrWideShift(const Instruction* inst, - const RegType& long_lo_type, - const RegType& long_hi_type, - const RegType& int_type) + RegType::Kind long_lo_kind, + RegType::Kind int_kind) REQUIRES_SHARED(Locks::mutator_lock_) { const uint32_t vregA = inst->VRegA_12x(); const uint32_t vregB = inst->VRegB_12x(); - if (VerifyRegisterTypeWide(vregA, long_lo_type, long_hi_type) && - VerifyRegisterType(vregB, int_type)) { - work_line_->SetRegisterTypeWide(vregA, long_lo_type, long_hi_type); + if (VerifyRegisterTypeWide(vregA, long_lo_kind) && + VerifyRegisterType(vregB, int_kind)) { + RegType::Kind long_hi_kind = RegType::ToHighHalf(long_lo_kind); + work_line_->SetRegisterTypeWide(vregA, long_lo_kind, long_hi_kind); } } @@ -925,24 +986,24 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { * If "check_boolean_op" is set, we use the constant value in vC. */ void CheckLiteralOp(const Instruction* inst, - const RegType& dst_type, - const RegType& src_type, + RegType::Kind dst_kind, + RegType::Kind src_kind, bool check_boolean_op, bool is_lit16) REQUIRES_SHARED(Locks::mutator_lock_) { const uint32_t vregA = is_lit16 ? inst->VRegA_22s() : inst->VRegA_22b(); const uint32_t vregB = is_lit16 ? inst->VRegB_22s() : inst->VRegB_22b(); - if (VerifyRegisterType(vregB, src_type)) { + if (VerifyRegisterType(vregB, src_kind)) { if (check_boolean_op) { - DCHECK(dst_type.IsInteger()); + DCHECK_EQ(dst_kind, RegType::Kind::kInteger); /* check vB with the call, then check the constant manually */ const uint32_t val = is_lit16 ? inst->VRegC_22s() : inst->VRegC_22b(); if (work_line_->GetRegisterType(this, vregB).IsBooleanTypes() && (val == 0 || val == 1)) { - work_line_->SetRegisterType<LockOp::kClear>(vregA, reg_types_.Boolean()); + work_line_->SetRegisterType(vregA, RegType::Kind::kBoolean); return; } } - work_line_->SetRegisterType<LockOp::kClear>(vregA, dst_type); + work_line_->SetRegisterType(vregA, dst_kind); } } @@ -950,7 +1011,7 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { return &GetModifiableInstructionFlags(work_insn_idx_); } - const RegType& DetermineCat1Constant(int32_t value) + RegType::Kind DetermineCat1Constant(int32_t value) REQUIRES_SHARED(Locks::mutator_lock_); ALWAYS_INLINE bool FailOrAbort(bool condition, const char* error_msg, uint32_t work_insn_idx); @@ -1968,22 +2029,22 @@ bool MethodVerifier<kVerifierDebug>::SetTypesFromSignature() { } break; case 'Z': - reg_line->SetRegisterType<LockOp::kClear>(arg_start + cur_arg, reg_types_.Boolean()); + reg_line->SetRegisterType(arg_start + cur_arg, RegType::Kind::kBoolean); break; case 'C': - reg_line->SetRegisterType<LockOp::kClear>(arg_start + cur_arg, reg_types_.Char()); + reg_line->SetRegisterType(arg_start + cur_arg, RegType::Kind::kChar); break; case 'B': - reg_line->SetRegisterType<LockOp::kClear>(arg_start + cur_arg, reg_types_.Byte()); + reg_line->SetRegisterType(arg_start + cur_arg, RegType::Kind::kByte); break; case 'I': - reg_line->SetRegisterType<LockOp::kClear>(arg_start + cur_arg, reg_types_.Integer()); + reg_line->SetRegisterType(arg_start + cur_arg, RegType::Kind::kInteger); break; case 'S': - reg_line->SetRegisterType<LockOp::kClear>(arg_start + cur_arg, reg_types_.Short()); + reg_line->SetRegisterType(arg_start + cur_arg, RegType::Kind::kShort); break; case 'F': - reg_line->SetRegisterType<LockOp::kClear>(arg_start + cur_arg, reg_types_.Float()); + reg_line->SetRegisterType(arg_start + cur_arg, RegType::Kind::kFloat); break; case 'J': case 'D': { @@ -2291,6 +2352,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g RegisterLineArenaUniquePtr branch_line; RegisterLineArenaUniquePtr fallthrough_line; + using enum RegType::Kind; switch (inst->Opcode()) { case Instruction::NOP: /* @@ -2398,7 +2460,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g } else { /* check the register contents */ const uint32_t vregA = inst->VRegA_11x(); - bool success = VerifyRegisterType(vregA, return_type); + bool success = VerifyRegisterTypeWide(vregA, return_type.GetKind()); if (!success) { AppendToLastFailMessage(StringPrintf(" return-wide on invalid register v%d", vregA)); } @@ -2445,22 +2507,22 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g /* could be boolean, int, float, or a null reference */ case Instruction::CONST_4: { int32_t val = static_cast<int32_t>(inst->VRegB_11n() << 28) >> 28; - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_11n(), DetermineCat1Constant(val)); + work_line_->SetRegisterType(inst->VRegA_11n(), DetermineCat1Constant(val)); break; } case Instruction::CONST_16: { int16_t val = static_cast<int16_t>(inst->VRegB_21s()); - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_21s(), DetermineCat1Constant(val)); + work_line_->SetRegisterType(inst->VRegA_21s(), DetermineCat1Constant(val)); break; } case Instruction::CONST: { int32_t val = inst->VRegB_31i(); - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_31i(), DetermineCat1Constant(val)); + work_line_->SetRegisterType(inst->VRegA_31i(), DetermineCat1Constant(val)); break; } case Instruction::CONST_HIGH16: { int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16); - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_21h(), DetermineCat1Constant(val)); + work_line_->SetRegisterType(inst->VRegA_21h(), DetermineCat1Constant(val)); break; } /* could be long or double; resolved upon use */ @@ -2633,7 +2695,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g DCHECK_NE(failures_.size(), 0U); if (!is_checkcast) { - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_22c(), reg_types_.Boolean()); + work_line_->SetRegisterType(inst->VRegA_22c(), kBoolean); } break; // bad class } @@ -2664,7 +2726,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g if (is_checkcast) { work_line_->SetRegisterType<LockOp::kKeep>(inst->VRegA_21c(), res_type); } else { - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_22c(), reg_types_.Boolean()); + work_line_->SetRegisterType(inst->VRegA_22c(), kBoolean); } } break; @@ -2676,7 +2738,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g // ie not an array or null Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "array-length on non-array " << res_type; } else { - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_12x(), reg_types_.Integer()); + work_line_->SetRegisterType(inst->VRegA_12x(), kInteger); } } else { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "array-length on non-array " << res_type; @@ -2718,34 +2780,14 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g break; case Instruction::CMPL_FLOAT: case Instruction::CMPG_FLOAT: - if (!VerifyRegisterType(inst->VRegB_23x(), reg_types_.Float())) { - break; - } - if (!VerifyRegisterType(inst->VRegC_23x(), reg_types_.Float())) { - break; - } - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_23x(), reg_types_.Integer()); + CheckBinaryOp(inst, kInteger, kFloat, kFloat, /*check_boolean_op=*/ false); break; case Instruction::CMPL_DOUBLE: case Instruction::CMPG_DOUBLE: - if (!VerifyRegisterTypeWide(inst->VRegB_23x(), reg_types_.DoubleLo(), - reg_types_.DoubleHi())) { - break; - } - if (!VerifyRegisterTypeWide(inst->VRegC_23x(), reg_types_.DoubleLo(), - reg_types_.DoubleHi())) { - break; - } - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_23x(), reg_types_.Integer()); + CheckBinaryOpWideCmp(inst, kInteger, kDoubleLo, kDoubleLo); break; case Instruction::CMP_LONG: - if (!VerifyRegisterTypeWide(inst->VRegB_23x(), reg_types_.LongLo(), reg_types_.LongHi())) { - break; - } - if (!VerifyRegisterTypeWide(inst->VRegC_23x(), reg_types_.LongLo(), reg_types_.LongHi())) { - break; - } - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_23x(), reg_types_.Integer()); + CheckBinaryOpWideCmp(inst, kInteger, kLongLo, kLongLo); break; case Instruction::THROW: { const RegType& res_type = work_line_->GetRegisterType(this, inst->VRegA_11x()); @@ -2771,7 +2813,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g case Instruction::PACKED_SWITCH: case Instruction::SPARSE_SWITCH: /* verify that vAA is an integer, or can be converted to one */ - VerifyRegisterType(inst->VRegA_31t(), reg_types_.Integer()); + VerifyRegisterType(inst->VRegA_31t(), kInteger); break; case Instruction::FILL_ARRAY_DATA: { @@ -3321,69 +3363,62 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g } case Instruction::NEG_INT: case Instruction::NOT_INT: - CheckUnaryOp(inst, reg_types_.Integer(), reg_types_.Integer()); + CheckUnaryOp(inst, kInteger, kInteger); break; case Instruction::NEG_LONG: case Instruction::NOT_LONG: - CheckUnaryOpWide(inst, reg_types_.LongLo(), reg_types_.LongHi(), - reg_types_.LongLo(), reg_types_.LongHi()); + CheckUnaryOpWide(inst, kLongLo, kLongLo); break; case Instruction::NEG_FLOAT: - CheckUnaryOp(inst, reg_types_.Float(), reg_types_.Float()); + CheckUnaryOp(inst, kFloat, kFloat); break; case Instruction::NEG_DOUBLE: - CheckUnaryOpWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(), - reg_types_.DoubleLo(), reg_types_.DoubleHi()); + CheckUnaryOpWide(inst, kDoubleLo, kDoubleLo); break; case Instruction::INT_TO_LONG: - CheckUnaryOpToWide(inst, reg_types_.LongLo(), reg_types_.LongHi(), reg_types_.Integer()); + CheckUnaryOpToWide(inst, kLongLo, kInteger); break; case Instruction::INT_TO_FLOAT: - CheckUnaryOp(inst, reg_types_.Float(), reg_types_.Integer()); + CheckUnaryOp(inst, kFloat, kInteger); break; case Instruction::INT_TO_DOUBLE: - CheckUnaryOpToWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(), - reg_types_.Integer()); + CheckUnaryOpToWide(inst, kDoubleLo, kInteger); break; case Instruction::LONG_TO_INT: - CheckUnaryOpFromWide(inst, reg_types_.Integer(), reg_types_.LongLo(), reg_types_.LongHi()); + CheckUnaryOpFromWide(inst, kInteger, kLongLo); break; case Instruction::LONG_TO_FLOAT: - CheckUnaryOpFromWide(inst, reg_types_.Float(), reg_types_.LongLo(), reg_types_.LongHi()); + CheckUnaryOpFromWide(inst, kFloat, kLongLo); break; case Instruction::LONG_TO_DOUBLE: - CheckUnaryOpWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(), - reg_types_.LongLo(), reg_types_.LongHi()); + CheckUnaryOpWide(inst, kDoubleLo, kLongLo); break; case Instruction::FLOAT_TO_INT: - CheckUnaryOp(inst, reg_types_.Integer(), reg_types_.Float()); + CheckUnaryOp(inst, kInteger, kFloat); break; case Instruction::FLOAT_TO_LONG: - CheckUnaryOpToWide(inst, reg_types_.LongLo(), reg_types_.LongHi(), reg_types_.Float()); + CheckUnaryOpToWide(inst, kLongLo, kFloat); break; case Instruction::FLOAT_TO_DOUBLE: - CheckUnaryOpToWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(), reg_types_.Float()); + CheckUnaryOpToWide(inst, kDoubleLo, kFloat); break; case Instruction::DOUBLE_TO_INT: - CheckUnaryOpFromWide(inst, reg_types_.Integer(), - reg_types_.DoubleLo(), reg_types_.DoubleHi()); + CheckUnaryOpFromWide(inst, kInteger, kDoubleLo); break; case Instruction::DOUBLE_TO_LONG: - CheckUnaryOpWide(inst, reg_types_.LongLo(), reg_types_.LongHi(), - reg_types_.DoubleLo(), reg_types_.DoubleHi()); + CheckUnaryOpWide(inst, kLongLo, kDoubleLo); break; case Instruction::DOUBLE_TO_FLOAT: - CheckUnaryOpFromWide(inst, reg_types_.Float(), - reg_types_.DoubleLo(), reg_types_.DoubleHi()); + CheckUnaryOpFromWide(inst, kFloat, kDoubleLo); break; case Instruction::INT_TO_BYTE: - CheckUnaryOp(inst, reg_types_.Byte(), reg_types_.Integer()); + CheckUnaryOp(inst, kByte, kInteger); break; case Instruction::INT_TO_CHAR: - CheckUnaryOp(inst, reg_types_.Char(), reg_types_.Integer()); + CheckUnaryOp(inst, kChar, kInteger); break; case Instruction::INT_TO_SHORT: - CheckUnaryOp(inst, reg_types_.Short(), reg_types_.Integer()); + CheckUnaryOp(inst, kShort, kInteger); break; case Instruction::ADD_INT: @@ -3394,12 +3429,12 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g case Instruction::SHL_INT: case Instruction::SHR_INT: case Instruction::USHR_INT: - CheckBinaryOp(inst, reg_types_.Integer(), reg_types_.Integer(), reg_types_.Integer(), false); + CheckBinaryOp(inst, kInteger, kInteger, kInteger, /*check_boolean_op=*/ false); break; case Instruction::AND_INT: case Instruction::OR_INT: case Instruction::XOR_INT: - CheckBinaryOp(inst, reg_types_.Integer(), reg_types_.Integer(), reg_types_.Integer(), true); + CheckBinaryOp(inst, kInteger, kInteger, kInteger, /*check_boolean_op=*/ true); break; case Instruction::ADD_LONG: case Instruction::SUB_LONG: @@ -3409,31 +3444,27 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g case Instruction::AND_LONG: case Instruction::OR_LONG: case Instruction::XOR_LONG: - CheckBinaryOpWide(inst, reg_types_.LongLo(), reg_types_.LongHi(), - reg_types_.LongLo(), reg_types_.LongHi(), - reg_types_.LongLo(), reg_types_.LongHi()); + CheckBinaryOpWide(inst, kLongLo, kLongLo, kLongLo); break; case Instruction::SHL_LONG: case Instruction::SHR_LONG: case Instruction::USHR_LONG: /* shift distance is Int, making these different from other binary operations */ - CheckBinaryOpWideShift(inst, reg_types_.LongLo(), reg_types_.LongHi(), reg_types_.Integer()); + CheckBinaryOpWideShift(inst, kLongLo, kInteger); break; case Instruction::ADD_FLOAT: case Instruction::SUB_FLOAT: case Instruction::MUL_FLOAT: case Instruction::DIV_FLOAT: case Instruction::REM_FLOAT: - CheckBinaryOp(inst, reg_types_.Float(), reg_types_.Float(), reg_types_.Float(), false); + CheckBinaryOp(inst, kFloat, kFloat, kFloat, /*check_boolean_op=*/ false); break; case Instruction::ADD_DOUBLE: case Instruction::SUB_DOUBLE: case Instruction::MUL_DOUBLE: case Instruction::DIV_DOUBLE: case Instruction::REM_DOUBLE: - CheckBinaryOpWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(), - reg_types_.DoubleLo(), reg_types_.DoubleHi(), - reg_types_.DoubleLo(), reg_types_.DoubleHi()); + CheckBinaryOpWide(inst, kDoubleLo, kDoubleLo, kDoubleLo); break; case Instruction::ADD_INT_2ADDR: case Instruction::SUB_INT_2ADDR: @@ -3442,18 +3473,15 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g case Instruction::SHL_INT_2ADDR: case Instruction::SHR_INT_2ADDR: case Instruction::USHR_INT_2ADDR: - CheckBinaryOp2addr( - inst, reg_types_.Integer(), reg_types_.Integer(), reg_types_.Integer(), false); + CheckBinaryOp2addr(inst, kInteger, kInteger, kInteger, /*check_boolean_op=*/ false); break; case Instruction::AND_INT_2ADDR: case Instruction::OR_INT_2ADDR: case Instruction::XOR_INT_2ADDR: - CheckBinaryOp2addr( - inst, reg_types_.Integer(), reg_types_.Integer(), reg_types_.Integer(), true); + CheckBinaryOp2addr(inst, kInteger, kInteger, kInteger, /*check_boolean_op=*/ true); break; case Instruction::DIV_INT_2ADDR: - CheckBinaryOp2addr( - inst, reg_types_.Integer(), reg_types_.Integer(), reg_types_.Integer(), false); + CheckBinaryOp2addr(inst, kInteger, kInteger, kInteger, /*check_boolean_op=*/ false); break; case Instruction::ADD_LONG_2ADDR: case Instruction::SUB_LONG_2ADDR: @@ -3463,43 +3491,38 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g case Instruction::AND_LONG_2ADDR: case Instruction::OR_LONG_2ADDR: case Instruction::XOR_LONG_2ADDR: - CheckBinaryOp2addrWide(inst, reg_types_.LongLo(), reg_types_.LongHi(), - reg_types_.LongLo(), reg_types_.LongHi(), - reg_types_.LongLo(), reg_types_.LongHi()); + CheckBinaryOp2addrWide(inst, kLongLo, kLongLo, kLongLo); break; case Instruction::SHL_LONG_2ADDR: case Instruction::SHR_LONG_2ADDR: case Instruction::USHR_LONG_2ADDR: - CheckBinaryOp2addrWideShift( - inst, reg_types_.LongLo(), reg_types_.LongHi(), reg_types_.Integer()); + CheckBinaryOp2addrWideShift(inst, kLongLo, kInteger); break; case Instruction::ADD_FLOAT_2ADDR: case Instruction::SUB_FLOAT_2ADDR: case Instruction::MUL_FLOAT_2ADDR: case Instruction::DIV_FLOAT_2ADDR: case Instruction::REM_FLOAT_2ADDR: - CheckBinaryOp2addr(inst, reg_types_.Float(), reg_types_.Float(), reg_types_.Float(), false); + CheckBinaryOp2addr(inst, kFloat, kFloat, kFloat, /*check_boolean_op=*/ false); break; case Instruction::ADD_DOUBLE_2ADDR: case Instruction::SUB_DOUBLE_2ADDR: case Instruction::MUL_DOUBLE_2ADDR: case Instruction::DIV_DOUBLE_2ADDR: case Instruction::REM_DOUBLE_2ADDR: - CheckBinaryOp2addrWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(), - reg_types_.DoubleLo(), reg_types_.DoubleHi(), - reg_types_.DoubleLo(), reg_types_.DoubleHi()); + CheckBinaryOp2addrWide(inst, kDoubleLo, kDoubleLo, kDoubleLo); break; case Instruction::ADD_INT_LIT16: case Instruction::RSUB_INT_LIT16: case Instruction::MUL_INT_LIT16: case Instruction::DIV_INT_LIT16: case Instruction::REM_INT_LIT16: - CheckLiteralOp(inst, reg_types_.Integer(), reg_types_.Integer(), false, true); + CheckLiteralOp(inst, kInteger, kInteger, /*check_boolean_op=*/ false, /*is_lit16=*/ true); break; case Instruction::AND_INT_LIT16: case Instruction::OR_INT_LIT16: case Instruction::XOR_INT_LIT16: - CheckLiteralOp(inst, reg_types_.Integer(), reg_types_.Integer(), true, true); + CheckLiteralOp(inst, kInteger, kInteger, /*check_boolean_op=*/ true, /*is_lit16=*/ true); break; case Instruction::ADD_INT_LIT8: case Instruction::RSUB_INT_LIT8: @@ -3509,12 +3532,12 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g case Instruction::SHL_INT_LIT8: case Instruction::SHR_INT_LIT8: case Instruction::USHR_INT_LIT8: - CheckLiteralOp(inst, reg_types_.Integer(), reg_types_.Integer(), false, false); + CheckLiteralOp(inst, kInteger, kInteger, /*check_boolean_op=*/ false, /*is_lit16=*/ false); break; case Instruction::AND_INT_LIT8: case Instruction::OR_INT_LIT8: case Instruction::XOR_INT_LIT8: - CheckLiteralOp(inst, reg_types_.Integer(), reg_types_.Integer(), true, false); + CheckLiteralOp(inst, kInteger, kInteger, /*check_boolean_op=*/ true, /*is_lit16=*/ false); break; /* These should never appear during verification. */ @@ -4468,7 +4491,7 @@ void MethodVerifier<kVerifierDebug>::VerifyNewArray(const Instruction* inst, Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "new-array on non-array class " << res_type; } else if (!is_filled) { /* make sure "size" register is valid type */ - VerifyRegisterType(inst->VRegB_22c(), reg_types_.Integer()); + VerifyRegisterType(inst->VRegB_22c(), RegType::Kind::kInteger); /* set register type to array class */ work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_22c(), res_type); } else { @@ -4512,7 +4535,7 @@ void MethodVerifier<kVerifierDebug>::VerifyAGet(const Instruction* inst, } else if (insn_type.IsInteger()) { // Pick a non-zero constant (to distinguish with null) that can fit in any primitive. // We cannot use 'insn_type' as it could be a float array or an int array. - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_23x(), DetermineCat1Constant(1)); + work_line_->SetRegisterType(inst->VRegA_23x(), DetermineCat1Constant(1)); } else if (insn_type.IsCategory1Types()) { // Category 1 // The 'insn_type' is exactly the type we need. @@ -4534,7 +4557,7 @@ void MethodVerifier<kVerifierDebug>::VerifyAGet(const Instruction* inst, Fail(VERIFY_ERROR_NO_CLASS) << "cannot verify aget for " << array_type << " because of missing class"; // Approximate with java.lang.Object[]. - work_line_->SetRegisterType<LockOp::kClear>(inst->VRegA_23x(), reg_types_.JavaLangObject()); + work_line_->SetRegisterType(inst->VRegA_23x(), RegType::Kind::kJavaLangObject); } } else { /* verify the class */ @@ -5017,26 +5040,26 @@ const RegType& MethodVerifier<kVerifierDebug>::GetMethodReturnType() { } template <bool kVerifierDebug> -const RegType& MethodVerifier<kVerifierDebug>::DetermineCat1Constant(int32_t value) { +RegType::Kind MethodVerifier<kVerifierDebug>::DetermineCat1Constant(int32_t value) { // Imprecise constant type. if (value < -32768) { - return reg_types_.IntegerConstant(); + return RegType::Kind::kIntegerConstant; } else if (value < -128) { - return reg_types_.ShortConstant(); + return RegType::Kind::kShortConstant; } else if (value < 0) { - return reg_types_.ByteConstant(); + return RegType::Kind::kByteConstant; } else if (value == 0) { - return reg_types_.Zero(); + return RegType::Kind::kZero; } else if (value == 1) { - return reg_types_.BooleanConstant(); + return RegType::Kind::kBooleanConstant; } else if (value < 128) { - return reg_types_.PositiveByteConstant(); + return RegType::Kind::kPositiveByteConstant; } else if (value < 32768) { - return reg_types_.PositiveShortConstant(); + return RegType::Kind::kPositiveShortConstant; } else if (value < 65536) { - return reg_types_.CharConstant(); + return RegType::Kind::kCharConstant; } else { - return reg_types_.IntegerConstant(); + return RegType::Kind::kIntegerConstant; } } |