Provide a convenience for logging types that don't have an operator<<.
Change-Id: I650b852ded67576dc5ec7c8e57732cfb49f1ecd6
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index d521e91..79a455e 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -890,12 +890,9 @@
DexVerifier verifier(method);
verifier.Verify();
- LogMessage log(__FILE__, __LINE__, INFO, -1);
- log.stream() << "Dump of method " << PrettyMethod(method) << " "
- << verifier.fail_messages_.str();
- log.stream() << std::endl << verifier.info_messages_.str();
-
- verifier.Dump(log.stream());
+ LOG(INFO) << "Dump of method " << PrettyMethod(method) << " "
+ << verifier.fail_messages_.str() << std::endl
+ << verifier.info_messages_.str() << Dumpable<DexVerifier>(verifier);
}
DexVerifier::DexVerifier(Method* method) : java_lang_throwable_(NULL), work_insn_idx_(-1),
diff --git a/src/logging.h b/src/logging.h
index 2e7856e..b653931 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -171,6 +171,32 @@
void HexDump(const void* address, size_t byte_count, bool show_actual_address = false);
+// A convenience to allow any class with a "Dump(std::ostream& os)" member function
+// but without an operator<< to be used as if it had an operator<<. Use like this:
+//
+// os << Dumpable<MyType>(my_type_instance);
+//
+template<typename T>
+class Dumpable {
+ public:
+ explicit Dumpable(T& value) : value_(value) {
+ }
+
+ void Dump(std::ostream& os) const {
+ value_.Dump(os);
+ }
+
+ private:
+ T& value_;
+ DISALLOW_COPY_AND_ASSIGN(Dumpable);
+};
+
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const Dumpable<T>& rhs) {
+ rhs.Dump(os);
+ return os;
+}
+
} // namespace art
#endif // ART_SRC_LOGGING_H_
diff --git a/src/object.cc b/src/object.cc
index 343f643..e59e79a 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -782,7 +782,7 @@
if ((flags & kDumpClassInitialized) != 0) {
os << ' ' << GetStatus();
}
- os << std::endl;
+ os << "\n";
return;
}
diff --git a/src/runtime.cc b/src/runtime.cc
index 9c923fb..54d7ec6 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -76,27 +76,26 @@
instance_ = NULL;
}
+struct AbortState {
+ void Dump(std::ostream& os) {
+ os << "Runtime aborting...\n";
+ Thread* self = Thread::Current();
+ if (self == NULL) {
+ os << "(Aborting thread was not attached to runtime!)\n";
+ } else {
+ self->Dump(os, true);
+ }
+ }
+};
+
void Runtime::Abort(const char* file, int line) {
// Get any pending output out of the way.
fflush(NULL);
// Many people have difficulty distinguish aborts from crashes,
// so be explicit.
- {
- LogMessage log(file, line, ERROR, -1);
- log.stream() << "Runtime aborting..." << std::endl;
- // Add Java stack trace if possible
- Thread* thread = Thread::Current();
- if (thread != NULL) {
- log.stream() << "Java stack trace of aborting thread:" << std::endl;
- thread->DumpStack(log.stream());
- if (thread->IsExceptionPending()) {
- Throwable* e = thread->GetException();
- log.stream() << "Pending exception on thread: " << PrettyTypeOf(e) << std::endl;
- log.stream() << e->Dump();
- }
- }
- }
+ AbortState state;
+ LOG(ERROR) << Dumpable<AbortState>(state);
// Perform any platform-specific pre-abort actions.
PlatformAbort(file, line);
diff --git a/src/thread.cc b/src/thread.cc
index 54d2e6c..841ea9b 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -344,9 +344,13 @@
CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
}
-void Thread::Dump(std::ostream& os) const {
+void Thread::Dump(std::ostream& os, bool dump_pending_exception) const {
DumpState(os);
DumpStack(os);
+ if (dump_pending_exception && IsExceptionPending()) {
+ os << "Pending " << PrettyTypeOf(GetException()) << " on thread:\n";
+ os << GetException()->Dump();
+ }
}
std::string GetSchedulerGroup(pid_t tid) {
diff --git a/src/thread.h b/src/thread.h
index 975edfc..ac97ebe 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -180,7 +180,7 @@
static Thread* FromManagedThread(JNIEnv* env, jobject thread);
static uint32_t LockOwnerFromThreadLock(Object* thread_lock);
- void Dump(std::ostream& os) const;
+ void Dump(std::ostream& os, bool dump_pending_exception = false) const;
State GetState() const {
return state_;
diff --git a/src/thread_list.cc b/src/thread_list.cc
index a77b8f6..6da5e68 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -371,9 +371,7 @@
Thread* self = Thread::Current();
if (verbose_) {
- LogMessage log(__FILE__, __LINE__, INFO, -1);
- log.stream() << "ThreadList::Register() " << *self << "\n";
- self->Dump(log.stream());
+ LOG(INFO) << "ThreadList::Register() " << *self << "\n" << Dumpable<Thread>(*self);
}
ThreadListLocker locker(this);