diff options
-rw-r--r-- | libartbase/base/arena_containers.h | 4 | ||||
-rw-r--r-- | libartbase/base/scoped_arena_containers.h | 4 | ||||
-rw-r--r-- | runtime/verifier/method_verifier-inl.h | 2 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 70 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 16 |
5 files changed, 49 insertions, 47 deletions
diff --git a/libartbase/base/arena_containers.h b/libartbase/base/arena_containers.h index e93c8d7bd0..78c5d43d59 100644 --- a/libartbase/base/arena_containers.h +++ b/libartbase/base/arena_containers.h @@ -19,6 +19,7 @@ #include <deque> #include <forward_list> +#include <list> #include <queue> #include <set> #include <stack> @@ -54,6 +55,9 @@ template <typename T> using ArenaForwardList = std::forward_list<T, ArenaAllocatorAdapter<T>>; template <typename T> +using ArenaList = std::list<T, ArenaAllocatorAdapter<T>>; + +template <typename T> using ArenaQueue = std::queue<T, ArenaDeque<T>>; template <typename T> diff --git a/libartbase/base/scoped_arena_containers.h b/libartbase/base/scoped_arena_containers.h index ee9a7461f8..2fbf555a00 100644 --- a/libartbase/base/scoped_arena_containers.h +++ b/libartbase/base/scoped_arena_containers.h @@ -19,6 +19,7 @@ #include <deque> #include <forward_list> +#include <list> #include <queue> #include <set> #include <type_traits> @@ -52,6 +53,9 @@ template <typename T> using ScopedArenaForwardList = std::forward_list<T, ScopedArenaAllocatorAdapter<T>>; template <typename T> +using ScopedArenaList = std::list<T, ScopedArenaAllocatorAdapter<T>>; + +template <typename T> using ScopedArenaQueue = std::queue<T, ScopedArenaDeque<T>>; template <typename T> diff --git a/runtime/verifier/method_verifier-inl.h b/runtime/verifier/method_verifier-inl.h index a13a58eede..762f1d6b85 100644 --- a/runtime/verifier/method_verifier-inl.h +++ b/runtime/verifier/method_verifier-inl.h @@ -35,7 +35,7 @@ inline MethodReference MethodVerifier::GetMethodReference() const { } inline bool MethodVerifier::HasFailures() const { - return !failure_messages_.empty(); + return !failures_.empty(); } } // namespace verifier diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 51eef745d9..68266f3335 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -201,18 +201,15 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { // Adds the given string to the beginning of the last failure message. void PrependToLastFailMessage(std::string prepend) { - size_t failure_num = failure_messages_.size(); - DCHECK_NE(failure_num, 0U); - std::ostringstream* last_fail_message = failure_messages_[failure_num - 1]; - prepend += last_fail_message->str(); - failure_messages_[failure_num - 1] = new std::ostringstream(prepend, std::ostringstream::ate); - delete last_fail_message; + MessageOStream* last_fail_message = &LastFailureMessageStream(); + prepend += last_fail_message->view(); + last_fail_message->str(std::move(prepend)); } // Return the last failure message stream for appending. - std::ostream& LastFailureMessageStream() { - DCHECK(!failure_messages_.empty()); - return *failure_messages_.back(); + MessageOStream& LastFailureMessageStream() { + DCHECK(!failures_.empty()); + return failures_.back().message; } /* @@ -1314,9 +1311,8 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { // Dump the failures encountered by the verifier. std::ostream& DumpFailures(std::ostream& os) { - DCHECK_EQ(failures_.size(), failure_messages_.size()); - for (const auto* stream : failure_messages_) { - os << stream->str() << "\n"; + for (const VerifyErrorAndMessage& veam : failures_) { + os << veam.message.view() << "\n"; } return os; } @@ -2508,7 +2504,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyMethod() { if (register_line != nullptr) { if (work_line_->CompareLine(register_line) != 0) { Dump(LOG_STREAM(FATAL_WITHOUT_ABORT)); - LOG(FATAL_WITHOUT_ABORT) << InfoMessages().str(); + LOG(FATAL_WITHOUT_ABORT) << InfoMessages().view(); LOG(FATAL) << "work_line diverged in " << dex_file_->PrettyMethod(dex_method_idx_) << "@" << reinterpret_cast<void*>(work_insn_idx_) << "\n" << " work_line=" << work_line_->Dump(this) << "\n" @@ -2581,7 +2577,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyMethod() { // To dump the state of the verify after a method, do something like: // if (dex_file_->PrettyMethod(dex_method_idx_) == // "boolean java.lang.String.equals(java.lang.Object)") { - // LOG(INFO) << InfoMessages().str(); + // LOG(INFO) << InfoMessages().view(); // } } return true; @@ -3613,8 +3609,8 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_POLYMORPHIC, is_range); if (called_method == nullptr) { // Convert potential soft failures in VerifyInvocationArgs() to hard errors. - if (failure_messages_.size() > 0) { - std::string message = failure_messages_.back()->str(); + if (failures_.size() > 0) { + std::string_view message = failures_.back().message.view(); Fail(VERIFY_ERROR_BAD_CLASS_HARD) << message; } else { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invoke-polymorphic verification failure."; @@ -3871,13 +3867,11 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g if (flags_.have_pending_hard_failure_) { if (IsAotMode()) { /* When AOT compiling, check that the last failure is a hard failure */ - if (failures_[failures_.size() - 1] != VERIFY_ERROR_BAD_CLASS_HARD) { + DCHECK(!failures_.empty()); + if (failures_.back().error != VERIFY_ERROR_BAD_CLASS_HARD) { LOG(ERROR) << "Pending failures:"; - for (auto& error : failures_) { - LOG(ERROR) << error; - } - for (auto& error_msg : failure_messages_) { - LOG(ERROR) << error_msg->str(); + for (const VerifyErrorAndMessage& veam : failures_) { + LOG(ERROR) << veam.error << " " << veam.message.view(); } LOG(FATAL) << "Pending hard failure, but last failure not hard."; } @@ -5372,6 +5366,7 @@ MethodVerifier::MethodVerifier(Thread* self, dex_file_(reg_types->GetDexFile()), class_def_(class_def), code_item_accessor_(*dex_file_, code_item), + failures_(allocator_.Adapter(kArenaAllocVerifier)), flags_{ .have_pending_hard_failure_ = false, .have_pending_runtime_throw_failure_ = false }, const_flags_{ .aot_mode_ = aot_mode, .can_load_classes_ = reg_types->CanLoadClasses() }, encountered_failure_types_(0), @@ -5380,10 +5375,6 @@ MethodVerifier::MethodVerifier(Thread* self, link_(nullptr) { } -MethodVerifier::~MethodVerifier() { - STLDeleteElements(&failure_messages_); -} - MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, ArenaPool* arena_pool, RegTypeCache* reg_types, @@ -5487,7 +5478,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, << reg_types->GetDexFile()->PrettyMethod(method_idx) << "\n"); } if (kVerifierDebug) { - LOG(INFO) << verifier.InfoMessages().str(); + LOG(INFO) << verifier.InfoMessages().view(); verifier.Dump(LOG_STREAM(INFO)); } if (CanRuntimeHandleVerificationFailure(verifier.encountered_failure_types_)) { @@ -5528,24 +5519,23 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, << reg_types->GetDexFile()->PrettyMethod(method_idx) << "\n"); } if (hard_failure_msg != nullptr) { - CHECK(!verifier.failure_messages_.empty()); - *hard_failure_msg = - verifier.failure_messages_[verifier.failure_messages_.size() - 1]->str(); + CHECK(!verifier.failures_.empty()); + *hard_failure_msg = verifier.failures_.back().message.view(); } result.kind = FailureKind::kHardFailure; if (kVerifierDebug || VLOG_IS_ON(verifier)) { - LOG(ERROR) << verifier.InfoMessages().str(); + LOG(ERROR) << verifier.InfoMessages().view(); verifier.Dump(LOG_STREAM(ERROR)); } // Under verifier-debug, dump the complete log into the error message. if (kVerifierDebug && hard_failure_msg != nullptr) { hard_failure_msg->append("\n"); - hard_failure_msg->append(verifier.InfoMessages().str()); + hard_failure_msg->append(verifier.InfoMessages().view()); hard_failure_msg->append("\n"); std::ostringstream oss; verifier.Dump(oss); - hard_failure_msg->append(oss.str()); + hard_failure_msg->append(oss.view()); } } if (kTimeVerifyMethod) { @@ -5591,7 +5581,7 @@ MethodVerifier* MethodVerifier::CalculateVerificationInfo( verifier->Verify(); if (VLOG_IS_ON(verifier)) { verifier->DumpFailures(VLOG_STREAM(verifier)); - VLOG(verifier) << verifier->InfoMessages().str(); + VLOG(verifier) << verifier->InfoMessages().view(); verifier->Dump(VLOG_STREAM(verifier)); } if (verifier->flags_.have_pending_hard_failure_) { @@ -5630,7 +5620,7 @@ void MethodVerifier::VerifyMethodAndDump(Thread* self, api_level); verifier.Verify(); verifier.DumpFailures(vios->Stream()); - vios->Stream() << verifier.InfoMessages().str(); + vios->Stream() << verifier.InfoMessages().view(); // Only dump if no hard failures. Otherwise the verifier may be not fully initialized // and querying any info is dangerous/can abort. if (!verifier.flags_.have_pending_hard_failure_) { @@ -5737,12 +5727,10 @@ std::ostream& MethodVerifier::Fail(VerifyError error, bool pending_exc) { CHECK_NE(error, VERIFY_ERROR_BAD_CLASS_HARD); } - failures_.push_back(error); - std::string location(StringPrintf("%s: [0x%X] ", dex_file_->PrettyMethod(dex_method_idx_).c_str(), - work_insn_idx_)); - std::ostringstream* failure_message = new std::ostringstream(location, std::ostringstream::ate); - failure_messages_.push_back(failure_message); - return *failure_message; + std::string location = + StringPrintf("%s: [0x%X] ", dex_file_->PrettyMethod(dex_method_idx_).c_str(), work_insn_idx_); + failures_.emplace_back(error, location, failures_.get_allocator()); + return failures_.back().message; } ScopedNewLine MethodVerifier::LogVerifyInfo() { diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 13631850b7..36c033ab64 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -156,7 +156,7 @@ class MethodVerifier { uint32_t api_level) REQUIRES_SHARED(Locks::mutator_lock_); - virtual ~MethodVerifier(); + virtual ~MethodVerifier() {} const CodeItemDataAccessor& CodeItem() const { return code_item_accessor_; @@ -331,10 +331,16 @@ class MethodVerifier { // Owned, but not unique_ptr since insn_flags_ are allocated in arenas. ArenaUniquePtr<InstructionFlags[]> insn_flags_; - // The types of any error that occurs. - std::vector<VerifyError> failures_; - // Error messages associated with failures. - std::vector<std::ostringstream*> failure_messages_; + // The types of any error that occurs and associated error messages. + using MessageOStream = + std::basic_ostringstream<char, std::char_traits<char>, ArenaAllocatorAdapter<char>>; + struct VerifyErrorAndMessage { + VerifyErrorAndMessage(VerifyError e, const std::string& location, ArenaAllocatorAdapter<char> a) + : error(e), message(location, std::ios_base::ate, a) {} + VerifyError error; + MessageOStream message; + }; + ArenaList<VerifyErrorAndMessage> failures_; struct { // Is there a pending hard failure? |