summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/verifier/method_verifier.cc174
1 files changed, 87 insertions, 87 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index b0e9d440ee..d0827ba0b2 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2817,98 +2817,104 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g
}
case Instruction::RETURN_VOID:
- if (!IsInstanceConstructor() || work_line_->CheckConstructorReturn(this)) {
- if (!GetMethodReturnType().IsConflict()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void not expected";
- return false;
- }
+ if (IsInstanceConstructor() && UNLIKELY(!work_line_->CheckConstructorReturn(this))) {
+ return false;
+ }
+ if (!GetMethodReturnType().IsConflict()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void not expected";
+ return false;
}
break;
- case Instruction::RETURN:
- if (!IsInstanceConstructor() || work_line_->CheckConstructorReturn(this)) {
- /* check the method signature */
- const RegType& return_type = GetMethodReturnType();
- if (!return_type.IsCategory1Types()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected non-category 1 return type "
- << return_type;
- return false;
- } else {
- // Compilers may generate synthetic functions that write byte values into boolean fields.
- // Also, it may use integer values for boolean, byte, short, and character return types.
- const uint32_t vregA = inst->VRegA_11x(inst_data);
- const RegType& src_type = work_line_->GetRegisterType(this, vregA);
- bool use_src = ((return_type.IsBoolean() && src_type.IsByte()) ||
- ((return_type.IsBoolean() || return_type.IsByte() ||
- return_type.IsShort() || return_type.IsChar()) &&
- src_type.IsInteger()));
- /* check the register contents */
- bool success = VerifyRegisterType(vregA, use_src ? src_type : return_type);
- if (!success) {
- LastFailureMessageStream() << " return-1nr on invalid register v" << vregA;
- }
+ case Instruction::RETURN: {
+ if (IsInstanceConstructor() && UNLIKELY(!work_line_->CheckConstructorReturn(this))) {
+ return false;
+ }
+ /* check the method signature */
+ const RegType& return_type = GetMethodReturnType();
+ if (!return_type.IsCategory1Types()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected non-category 1 return type "
+ << return_type;
+ return false;
+ } else {
+ // Compilers may generate synthetic functions that write byte values into boolean fields.
+ // Also, it may use integer values for boolean, byte, short, and character return types.
+ const uint32_t vregA = inst->VRegA_11x(inst_data);
+ const RegType& src_type = work_line_->GetRegisterType(this, vregA);
+ bool use_src = ((return_type.IsBoolean() && src_type.IsByte()) ||
+ ((return_type.IsBoolean() || return_type.IsByte() ||
+ return_type.IsShort() || return_type.IsChar()) &&
+ src_type.IsInteger()));
+ /* check the register contents */
+ bool success = VerifyRegisterType(vregA, use_src ? src_type : return_type);
+ if (!success) {
+ LastFailureMessageStream() << " return-1nr on invalid register v" << vregA;
}
}
break;
- case Instruction::RETURN_WIDE:
- if (!IsInstanceConstructor() || work_line_->CheckConstructorReturn(this)) {
- /* check the method signature */
- const RegType& return_type = GetMethodReturnType();
- if (!return_type.IsCategory2Types()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-wide not expected";
- return false;
- } else {
- /* check the register contents */
- const uint32_t vregA = inst->VRegA_11x(inst_data);
- bool success = VerifyRegisterTypeWide(vregA, return_type.GetKind());
- if (!success) {
- LastFailureMessageStream() << " return-wide on invalid register v" << vregA;
- }
+ }
+ case Instruction::RETURN_WIDE: {
+ if (IsInstanceConstructor() && UNLIKELY(!work_line_->CheckConstructorReturn(this))) {
+ return false;
+ }
+ /* check the method signature */
+ const RegType& return_type = GetMethodReturnType();
+ if (!return_type.IsCategory2Types()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-wide not expected";
+ return false;
+ } else {
+ /* check the register contents */
+ const uint32_t vregA = inst->VRegA_11x(inst_data);
+ bool success = VerifyRegisterTypeWide(vregA, return_type.GetKind());
+ if (!success) {
+ LastFailureMessageStream() << " return-wide on invalid register v" << vregA;
}
}
break;
- case Instruction::RETURN_OBJECT:
- if (!IsInstanceConstructor() || work_line_->CheckConstructorReturn(this)) {
- const RegType& return_type = GetMethodReturnType();
- if (!return_type.IsReferenceTypes()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-object not expected";
+ }
+ case Instruction::RETURN_OBJECT: {
+ if (IsInstanceConstructor() && UNLIKELY(!work_line_->CheckConstructorReturn(this))) {
+ return false;
+ }
+ const RegType& return_type = GetMethodReturnType();
+ if (!return_type.IsReferenceTypes()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-object not expected";
+ return false;
+ } else {
+ /* return_type is the *expected* return type, not register value */
+ DCHECK(!return_type.IsZeroOrNull());
+ DCHECK(!return_type.IsUninitializedReference());
+ const uint32_t vregA = inst->VRegA_11x(inst_data);
+ const RegType& reg_type = work_line_->GetRegisterType(this, vregA);
+ // Disallow returning undefined, conflict & uninitialized values and verify that the
+ // reference in vAA is an instance of the "return_type."
+ if (reg_type.IsUndefined()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning undefined register";
return false;
- } else {
- /* return_type is the *expected* return type, not register value */
- DCHECK(!return_type.IsZeroOrNull());
- DCHECK(!return_type.IsUninitializedReference());
- const uint32_t vregA = inst->VRegA_11x(inst_data);
- const RegType& reg_type = work_line_->GetRegisterType(this, vregA);
- // Disallow returning undefined, conflict & uninitialized values and verify that the
- // reference in vAA is an instance of the "return_type."
- if (reg_type.IsUndefined()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning undefined register";
- return false;
- } else if (reg_type.IsConflict()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning register with conflict";
- return false;
- } else if (reg_type.IsUninitializedTypes()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning uninitialized object '"
- << reg_type << "'";
- return false;
- } else if (!reg_type.IsReferenceTypes()) {
- // We really do expect a reference here.
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-object returns a non-reference type "
- << reg_type;
+ } else if (reg_type.IsConflict()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning register with conflict";
+ return false;
+ } else if (reg_type.IsUninitializedTypes()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning uninitialized object '"
+ << reg_type << "'";
+ return false;
+ } else if (!reg_type.IsReferenceTypes()) {
+ // We really do expect a reference here.
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-object returns a non-reference type "
+ << reg_type;
+ return false;
+ } else if (!IsAssignableFrom(return_type, reg_type)) {
+ if (reg_type.IsUnresolvedTypes() || return_type.IsUnresolvedTypes()) {
+ Fail(VERIFY_ERROR_UNRESOLVED_TYPE_CHECK)
+ << " can't resolve returned type '" << return_type << "' or '" << reg_type << "'";
+ } else {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning '" << reg_type
+ << "', but expected from declaration '" << return_type << "'";
return false;
- } else if (!IsAssignableFrom(return_type, reg_type)) {
- if (reg_type.IsUnresolvedTypes() || return_type.IsUnresolvedTypes()) {
- Fail(VERIFY_ERROR_UNRESOLVED_TYPE_CHECK)
- << " can't resolve returned type '" << return_type << "' or '" << reg_type << "'";
- } else {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning '" << reg_type
- << "', but expected from declaration '" << return_type << "'";
- return false;
- }
}
}
}
break;
-
+ }
/* could be boolean, int, float, or a null reference */
case Instruction::CONST_4: {
int32_t val = static_cast<int32_t>(inst->VRegB_11n(inst_data) << 28) >> 28;
@@ -3122,18 +3128,12 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g
}
case Instruction::ARRAY_LENGTH: {
const RegType& res_type = work_line_->GetRegisterType(this, inst->VRegB_12x(inst_data));
- if (res_type.IsReferenceTypes()) {
- if (!res_type.IsArrayTypes() && !res_type.IsZeroOrNull()) {
- // ie not an array or null
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "array-length on non-array " << res_type;
- return false;
- } else {
- work_line_->SetRegisterType(inst->VRegA_12x(inst_data), kInteger);
- }
- } else {
+ if (!res_type.IsReferenceTypes() || (!res_type.IsArrayTypes() && !res_type.IsZeroOrNull())) {
+ // ie not an array or null
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "array-length on non-array " << res_type;
return false;
}
+ work_line_->SetRegisterType(inst->VRegA_12x(inst_data), kInteger);
break;
}
case Instruction::NEW_INSTANCE: {