summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libartbase/base/arena_containers.h4
-rw-r--r--libartbase/base/scoped_arena_containers.h4
-rw-r--r--runtime/verifier/method_verifier-inl.h2
-rw-r--r--runtime/verifier/method_verifier.cc70
-rw-r--r--runtime/verifier/method_verifier.h16
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?