summaryrefslogtreecommitdiff
path: root/runtime/verifier/method_verifier.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/verifier/method_verifier.cc')
-rw-r--r--runtime/verifier/method_verifier.cc419
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;
}
}