ART: Introduce CompatThrow
Add an "virtual" instruction flag to signal a historical throw
that is not captured by kThrow. Both kinds of instructions need
to capture the work line at the beginning of a verification step.
Long-term, remove CompatThrow.
"Annotate" return-object.
Bug: 121245951
Test: m test-art-host
Change-Id: I07e9f07da3ebcc9ccd1191ffc2c145b2c83a84f8
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index c4be933..6080875 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -120,6 +120,18 @@
kAccPut
};
+// Instruction types that are not marked as throwing (because they normally would not), but for
+// historical reasons may do so. These instructions cannot be marked kThrow as that would introduce
+// a general flow that is unwanted.
+//
+// Note: Not implemented as Instruction::Flags value as that set is full and we'd need to increase
+// the struct size (making it a non-power-of-two) for a single element.
+//
+// Note: This should eventually be removed.
+constexpr bool IsCompatThrow(Instruction::Code opcode) {
+ return opcode == Instruction::Code::RETURN_OBJECT;
+}
+
template <bool kVerifierDebug>
class MethodVerifier final : public ::art::verifier::MethodVerifier {
public:
@@ -2052,7 +2064,8 @@
* from the "successful" code path (e.g. a check-cast that "improves"
* a type) to be visible to the exception handler.
*/
- if ((opcode_flags & Instruction::kThrow) != 0 && CurrentInsnFlags()->IsInTry()) {
+ if (((opcode_flags & Instruction::kThrow) != 0 || IsCompatThrow(inst->Opcode())) &&
+ CurrentInsnFlags()->IsInTry()) {
saved_line_->CopyFromLine(work_line_.get());
} else if (kIsDebugBuild) {
saved_line_->FillWithGarbage();
@@ -5557,6 +5570,7 @@
int opcode_flags = Instruction::FlagsOf(inst.Opcode());
if ((opcode_flags & Instruction::kThrow) == 0 &&
+ !impl::IsCompatThrow(inst.Opcode()) &&
GetInstructionFlags(work_insn_idx_).IsInTry()) {
saved_line_->CopyFromLine(work_line_.get());
}