Tidy up logging.
Move gVerboseMethods to CompilerOptions. Now "--verbose-methods=" option to
dex2oat rather than runtime argument "-verbose-methods:".
Move ToStr and Dumpable out of logging.h, move LogMessageData into logging.cc
except for a forward declaration.
Remove ConstDumpable as Dump methods are all const (and make this so if not
currently true).
Make LogSeverity an enum and improve compile time assertions and type checking.
Remove log_severity.h that's only used in logging.h.
With system headers gone from logging.h, go add to .cc files missing system
header includes.
Also, make operator new in ValueObject private for compile time instantiation
checking.
Change-Id: I3228f614500ccc9b14b49c72b9821c8b0db3d641
diff --git a/runtime/base/bit_vector.cc b/runtime/base/bit_vector.cc
index 3d2f0de..1e0be3a 100644
--- a/runtime/base/bit_vector.cc
+++ b/runtime/base/bit_vector.cc
@@ -16,6 +16,8 @@
#include "bit_vector.h"
+#include <sstream>
+
#include "allocator.h"
#include "bit_vector-inl.h"
diff --git a/runtime/base/dumpable.h b/runtime/base/dumpable.h
new file mode 100644
index 0000000..3c316cc
--- /dev/null
+++ b/runtime/base/dumpable.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_BASE_DUMPABLE_H_
+#define ART_RUNTIME_BASE_DUMPABLE_H_
+
+#include "base/macros.h"
+
+namespace art {
+
+// 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 FINAL {
+ public:
+ explicit Dumpable(const T& value) : value_(value) {
+ }
+
+ void Dump(std::ostream& os) const {
+ value_.Dump(os);
+ }
+
+ private:
+ const 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_RUNTIME_BASE_DUMPABLE_H_
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
index 5af597b..46c3538 100644
--- a/runtime/base/logging.cc
+++ b/runtime/base/logging.cc
@@ -16,17 +16,25 @@
#include "logging.h"
+#include <sstream>
+
#include "base/mutex.h"
#include "runtime.h"
#include "thread-inl.h"
#include "utils.h"
+// Headers for LogMessage::LogLine.
+#ifdef HAVE_ANDROID_OS
+#include "cutils/log.h"
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
namespace art {
LogVerbosity gLogVerbosity;
-std::vector<std::string> gVerboseMethods;
-
unsigned int gAborting = 0;
static LogSeverity gMinimumLogSeverity = INFO;
@@ -47,14 +55,6 @@
: "art";
}
-// Configure logging based on ANDROID_LOG_TAGS environment variable.
-// We need to parse a string that looks like
-//
-// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
-//
-// The tag (or '*' for the global level) comes first, followed by a colon
-// and a letter indicating the minimum priority level we're expected to log.
-// This can be used to reveal or conceal logs with specific tags.
void InitLogging(char* argv[]) {
if (gCmdLine.get() != nullptr) {
return;
@@ -65,22 +65,22 @@
// Stash the command line for later use. We can use /proc/self/cmdline on Linux to recover this,
// but we don't have that luxury on the Mac, and there are a couple of argv[0] variants that are
// commonly used.
- if (argv != NULL) {
+ if (argv != nullptr) {
gCmdLine.reset(new std::string(argv[0]));
- for (size_t i = 1; argv[i] != NULL; ++i) {
+ for (size_t i = 1; argv[i] != nullptr; ++i) {
gCmdLine->append(" ");
gCmdLine->append(argv[i]);
}
gProgramInvocationName.reset(new std::string(argv[0]));
const char* last_slash = strrchr(argv[0], '/');
- gProgramInvocationShortName.reset(new std::string((last_slash != NULL) ? last_slash + 1
+ gProgramInvocationShortName.reset(new std::string((last_slash != nullptr) ? last_slash + 1
: argv[0]));
} else {
- // TODO: fall back to /proc/self/cmdline when argv is NULL on Linux
+ // TODO: fall back to /proc/self/cmdline when argv is NULL on Linux.
gCmdLine.reset(new std::string("<unset>"));
}
const char* tags = getenv("ANDROID_LOG_TAGS");
- if (tags == NULL) {
+ if (tags == nullptr) {
return;
}
@@ -119,47 +119,121 @@
}
}
-LogMessageData::LogMessageData(const char* file, int line, LogSeverity severity, int error)
- : file(file),
- line_number(line),
- severity(severity),
- error(error) {
- const char* last_slash = strrchr(file, '/');
- file = (last_slash == NULL) ? file : last_slash + 1;
-}
+// This indirection greatly reduces the stack impact of having
+// lots of checks/logging in a function.
+class LogMessageData {
+ public:
+ LogMessageData(const char* file, unsigned int line, LogSeverity severity, int error)
+ : file_(file),
+ line_number_(line),
+ severity_(severity),
+ error_(error) {
+ const char* last_slash = strrchr(file, '/');
+ file = (last_slash == nullptr) ? file : last_slash + 1;
+ }
+ const char * GetFile() const {
+ return file_;
+ }
+
+ unsigned int GetLineNumber() const {
+ return line_number_;
+ }
+
+ LogSeverity GetSeverity() const {
+ return severity_;
+ }
+
+ int GetError() const {
+ return error_;
+ }
+
+ std::ostream& GetBuffer() {
+ return buffer_;
+ }
+
+ std::string ToString() const {
+ return buffer_.str();
+ }
+
+ private:
+ std::ostringstream buffer_;
+ const char* const file_;
+ const unsigned int line_number_;
+ const LogSeverity severity_;
+ const int error_;
+
+ DISALLOW_COPY_AND_ASSIGN(LogMessageData);
+};
+
+
+LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity, int error)
+ : data_(new LogMessageData(file, line, severity, error)) {
+}
LogMessage::~LogMessage() {
- if (data_->severity < gMinimumLogSeverity) {
+ if (data_->GetSeverity() < gMinimumLogSeverity) {
return; // No need to format something we're not going to output.
}
// Finish constructing the message.
- if (data_->error != -1) {
- data_->buffer << ": " << strerror(data_->error);
+ if (data_->GetError() != -1) {
+ data_->GetBuffer() << ": " << strerror(data_->GetError());
}
- std::string msg(data_->buffer.str());
+ std::string msg(data_->ToString());
// Do the actual logging with the lock held.
{
MutexLock mu(Thread::Current(), *Locks::logging_lock_);
if (msg.find('\n') == std::string::npos) {
- LogLine(*data_, msg.c_str());
+ LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), msg.c_str());
} else {
msg += '\n';
size_t i = 0;
while (i < msg.size()) {
size_t nl = msg.find('\n', i);
msg[nl] = '\0';
- LogLine(*data_, &msg[i]);
+ LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), &msg[i]);
i = nl + 1;
}
}
}
// Abort if necessary.
- if (data_->severity == FATAL) {
+ if (data_->GetSeverity() == FATAL) {
Runtime::Abort();
}
}
+std::ostream& LogMessage::stream() {
+ return data_->GetBuffer();
+}
+
+#ifdef HAVE_ANDROID_OS
+static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
+ ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
+ ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
+};
+COMPILE_ASSERT(arraysize(kLogSeverityToAndroidLogPriority) == INTERNAL_FATAL + 1,
+ mismatch_in_size_of_kLogSeverityToAndroidLogPriority_and_values_in_LogSeverity);
+#endif
+
+void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity log_severity,
+ const char* message) {
+#ifdef HAVE_ANDROID_OS
+ const char* tag = ProgramInvocationShortName();
+ int priority = kLogSeverityToAndroidLogPriority[log_severity];
+ if (priority == ANDROID_LOG_FATAL) {
+ LOG_PRI(priority, tag, "%s:%u] %s", file, line, message);
+ } else {
+ LOG_PRI(priority, tag, "%s", message);
+ }
+#else
+ static const char* log_characters = "VDIWEFF";
+ CHECK_EQ(strlen(log_characters), INTERNAL_FATAL + 1U);
+ char severity = log_characters[log_severity];
+ fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n",
+ ProgramInvocationShortName(), severity, getpid(), ::art::GetTid(), file, line, message);
+#endif
+}
+
} // namespace art
diff --git a/runtime/base/logging.h b/runtime/base/logging.h
index cf3e763..5e8e994 100644
--- a/runtime/base/logging.h
+++ b/runtime/base/logging.h
@@ -17,29 +17,113 @@
#ifndef ART_RUNTIME_BASE_LOGGING_H_
#define ART_RUNTIME_BASE_LOGGING_H_
-#include <cerrno>
-#include <cstring>
-#include <iostream> // NOLINT
+#include <iostream>
#include <memory>
-#include <sstream>
-#include <signal.h>
-#include <vector>
#include "base/macros.h"
-#include "log_severity.h"
+namespace art {
+
+enum LogSeverity {
+ VERBOSE,
+ DEBUG,
+ INFO,
+ WARNING,
+ ERROR,
+ FATAL,
+ INTERNAL_FATAL, // For Runtime::Abort.
+};
+
+// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code,
+// and the "-verbose:" command line argument.
+struct LogVerbosity {
+ bool class_linker; // Enabled with "-verbose:class".
+ bool compiler;
+ bool gc;
+ bool heap;
+ bool jdwp;
+ bool jni;
+ bool monitor;
+ bool profiler;
+ bool signals;
+ bool startup;
+ bool third_party_jni; // Enabled with "-verbose:third-party-jni".
+ bool threads;
+ bool verifier;
+};
+
+// Global log verbosity setting, initialized by InitLogging.
+extern LogVerbosity gLogVerbosity;
+
+// 0 if not abort, non-zero if an abort is in progress. Used on fatal exit to prevents recursive
+// aborts. Global declaration allows us to disable some error checking to ensure fatal shutdown
+// makes forward progress.
+extern unsigned int gAborting;
+
+// Configure logging based on ANDROID_LOG_TAGS environment variable.
+// We need to parse a string that looks like
+//
+// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
+//
+// The tag (or '*' for the global level) comes first, followed by a colon
+// and a letter indicating the minimum priority level we're expected to log.
+// This can be used to reveal or conceal logs with specific tags.
+extern void InitLogging(char* argv[]);
+
+// Returns the command line used to invoke the current tool or nullptr if InitLogging hasn't been
+// performed.
+extern const char* GetCmdLine();
+
+// The command used to start the ART runtime, such as "/system/bin/dalvikvm". If InitLogging hasn't
+// been performed then just returns "art"
+extern const char* ProgramInvocationName();
+
+// A short version of the command used to start the ART runtime, such as "dalvikvm". If InitLogging
+// hasn't been performed then just returns "art"
+extern const char* ProgramInvocationShortName();
+
+// Logs a message to logcat on Android otherwise to stderr. If the severity is FATAL it also causes
+// an abort. For example: LOG(FATAL) << "We didn't expect to reach here";
+#define LOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, -1).stream()
+
+// A variant of LOG that also logs the current errno value. To be used when library calls fail.
+#define PLOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, errno).stream()
+
+// Marker that code is yet to be implemented.
+#define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
+
+// Is verbose logging enabled for the given module? Where the module is defined in LogVerbosity.
+#define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module)
+
+// Variant of LOG that logs when verbose logging is enabled for a module. For example,
+// VLOG(jni) << "A JNI operation was performed";
+#define VLOG(module) \
+ if (VLOG_IS_ON(module)) \
+ ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
+
+// Return the stream associated with logging for the given module.
+#define VLOG_STREAM(module) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
+
+// Check whether condition x holds and LOG(FATAL) if not. The value of the expression x is only
+// evaluated once. Extra logging can be appended using << after. For example,
+// CHECK(false == true) results in a log message of "Check failed: false == true".
#define CHECK(x) \
if (UNLIKELY(!(x))) \
- ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
+ ::art::LogMessage(__FILE__, __LINE__, ::art::FATAL, -1).stream() \
<< "Check failed: " #x << " "
+// Helper for CHECK_xx(x,y) macros.
#define CHECK_OP(LHS, RHS, OP) \
for (auto _values = ::art::MakeEagerEvaluator(LHS, RHS); \
UNLIKELY(!(_values.lhs OP _values.rhs)); /* empty */) \
- ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
+ ::art::LogMessage(__FILE__, __LINE__, ::art::FATAL, -1).stream() \
<< "Check failed: " << #LHS << " " << #OP << " " << #RHS \
<< " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") "
+
+// Check whether a condition holds between x and y, LOG(FATAL) if not. The value of the expressions
+// x and y is evaluated once. Extra logging can be appended using << after. For example,
+// CHECK_NE(0 == 1, false) results in "Check failed: false != false (0==1=false, false=false) ".
#define CHECK_EQ(x, y) CHECK_OP(x, y, ==)
#define CHECK_NE(x, y) CHECK_OP(x, y, !=)
#define CHECK_LE(x, y) CHECK_OP(x, y, <=)
@@ -47,22 +131,25 @@
#define CHECK_GE(x, y) CHECK_OP(x, y, >=)
#define CHECK_GT(x, y) CHECK_OP(x, y, >)
+// Helper for CHECK_STRxx(s1,s2) macros.
#define CHECK_STROP(s1, s2, sense) \
if (UNLIKELY((strcmp(s1, s2) == 0) != sense)) \
- LOG(FATAL) << "Check failed: " \
- << "\"" << s1 << "\"" \
- << (sense ? " == " : " != ") \
- << "\"" << s2 << "\""
+ LOG(::art::FATAL) << "Check failed: " \
+ << "\"" << s1 << "\"" \
+ << (sense ? " == " : " != ") \
+ << "\"" << s2 << "\""
+// Check for string (const char*) equality between s1 and s2, LOG(FATAL) if not.
#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true)
#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false)
+// Perform the pthread function call(args), LOG(FATAL) on error.
#define CHECK_PTHREAD_CALL(call, args, what) \
do { \
int rc = call args; \
if (rc != 0) { \
errno = rc; \
- PLOG(FATAL) << # call << " failed for " << what; \
+ PLOG(::art::FATAL) << # call << " failed for " << what; \
} \
} while (false)
@@ -74,81 +161,34 @@
// n / 2;
// }
#define CHECK_CONSTEXPR(x, out, dummy) \
- (UNLIKELY(!(x))) ? (LOG(FATAL) << "Check failed: " << #x out, dummy) :
+ (UNLIKELY(!(x))) ? (LOG(::art::FATAL) << "Check failed: " << #x out, dummy) :
-#ifndef NDEBUG
-#define DCHECK(x) CHECK(x)
-#define DCHECK_EQ(x, y) CHECK_EQ(x, y)
-#define DCHECK_NE(x, y) CHECK_NE(x, y)
-#define DCHECK_LE(x, y) CHECK_LE(x, y)
-#define DCHECK_LT(x, y) CHECK_LT(x, y)
-#define DCHECK_GE(x, y) CHECK_GE(x, y)
-#define DCHECK_GT(x, y) CHECK_GT(x, y)
-#define DCHECK_STREQ(s1, s2) CHECK_STREQ(s1, s2)
-#define DCHECK_STRNE(s1, s2) CHECK_STRNE(s1, s2)
-#define DCHECK_CONSTEXPR(x, out, dummy) CHECK_CONSTEXPR(x, out, dummy)
-
-#else // NDEBUG
-
-#define DCHECK(condition) \
- while (false) \
- CHECK(condition)
-
-#define DCHECK_EQ(val1, val2) \
- while (false) \
- CHECK_EQ(val1, val2)
-
-#define DCHECK_NE(val1, val2) \
- while (false) \
- CHECK_NE(val1, val2)
-
-#define DCHECK_LE(val1, val2) \
- while (false) \
- CHECK_LE(val1, val2)
-
-#define DCHECK_LT(val1, val2) \
- while (false) \
- CHECK_LT(val1, val2)
-
-#define DCHECK_GE(val1, val2) \
- while (false) \
- CHECK_GE(val1, val2)
-
-#define DCHECK_GT(val1, val2) \
- while (false) \
- CHECK_GT(val1, val2)
-
-#define DCHECK_STREQ(str1, str2) \
- while (false) \
- CHECK_STREQ(str1, str2)
-
-#define DCHECK_STRNE(str1, str2) \
- while (false) \
- CHECK_STRNE(str1, str2)
-
-#define DCHECK_CONSTEXPR(x, out, dummy) \
- (false && (x)) ? (dummy) :
-
+// DCHECKs are debug variants of CHECKs only enabled in debug builds. Generally CHECK should be
+// used unless profiling identifies a CHECK as being in performance critical code.
+#if defined(NDEBUG)
+static constexpr bool kEnableDChecks = false;
+#else
+static constexpr bool kEnableDChecks = true;
#endif
-#define LOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, -1).stream()
-#define PLOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, errno).stream()
+#define DCHECK(x) if (::art::kEnableDChecks) CHECK(x)
+#define DCHECK_EQ(x, y) if (::art::kEnableDChecks) CHECK_EQ(x, y)
+#define DCHECK_NE(x, y) if (::art::kEnableDChecks) CHECK_NE(x, y)
+#define DCHECK_LE(x, y) if (::art::kEnableDChecks) CHECK_LE(x, y)
+#define DCHECK_LT(x, y) if (::art::kEnableDChecks) CHECK_LT(x, y)
+#define DCHECK_GE(x, y) if (::art::kEnableDChecks) CHECK_GE(x, y)
+#define DCHECK_GT(x, y) if (::art::kEnableDChecks) CHECK_GT(x, y)
+#define DCHECK_STREQ(s1, s2) if (::art::kEnableDChecks) CHECK_STREQ(s1, s2)
+#define DCHECK_STRNE(s1, s2) if (::art::kEnableDChecks) CHECK_STRNE(s1, s2)
+#if defined(NDEBUG)
+#define DCHECK_CONSTEXPR(x, out, dummy)
+#else
+#define DCHECK_CONSTEXPR(x, out, dummy) CHECK_CONSTEXPR(x, out, dummy)
+#endif
-#define LG LOG(INFO)
-
-#define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
-
-#define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module)
-#define VLOG(module) if (VLOG_IS_ON(module)) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
-#define VLOG_STREAM(module) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
-
-//
-// Implementation details beyond this point.
-//
-
-namespace art {
-
+// Temporary class created to evaluate the LHS and RHS, used with MakeEagerEvaluator to infer the
+// types of LHS and RHS.
template <typename LHS, typename RHS>
struct EagerEvaluator {
EagerEvaluator(LHS l, RHS r) : lhs(l), rhs(r) { }
@@ -156,10 +196,14 @@
RHS rhs;
};
-// We want char*s to be treated as pointers, not strings. If you want them treated like strings,
-// you'd need to use CHECK_STREQ and CHECK_STRNE anyway to compare the characters rather than their
-// addresses. We could express this more succinctly with std::remove_const, but this is quick and
-// easy to understand, and works before we have C++0x. We rely on signed/unsigned warnings to
+// Helper function for CHECK_xx.
+template <typename LHS, typename RHS>
+static inline EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
+ return EagerEvaluator<LHS, RHS>(lhs, rhs);
+}
+
+// Explicitly instantiate EagerEvalue for pointers so that char*s aren't treated as strings. To
+// compare strings use CHECK_STREQ and CHECK_STRNE. We rely on signed/unsigned warnings to
// protect you against combinations not explicitly listed below.
#define EAGER_PTR_EVALUATOR(T1, T2) \
template <> struct EagerEvaluator<T1, T2> { \
@@ -182,153 +226,30 @@
EAGER_PTR_EVALUATOR(signed char*, const signed char*);
EAGER_PTR_EVALUATOR(signed char*, signed char*);
-template <typename LHS, typename RHS>
-EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
- return EagerEvaluator<LHS, RHS>(lhs, rhs);
-}
+// Data for the log message, not stored in LogMessage to avoid increasing the stack size.
+class LogMessageData;
-// This indirection greatly reduces the stack impact of having
-// lots of checks/logging in a function.
-struct LogMessageData {
- public:
- LogMessageData(const char* file, int line, LogSeverity severity, int error);
- std::ostringstream buffer;
- const char* const file;
- const int line_number;
- const LogSeverity severity;
- const int error;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LogMessageData);
-};
-
+// A LogMessage is a temporarily scoped object used by LOG and the unlikely part of a CHECK. The
+// destructor will abort if the severity is FATAL.
class LogMessage {
public:
- LogMessage(const char* file, int line, LogSeverity severity, int error)
- : data_(new LogMessageData(file, line, severity, error)) {
- }
+ LogMessage(const char* file, unsigned int line, LogSeverity severity, int error);
~LogMessage(); // TODO: enable LOCKS_EXCLUDED(Locks::logging_lock_).
- std::ostream& stream() {
- return data_->buffer;
- }
+ // Returns the stream associated with the message, the LogMessage performs output when it goes
+ // out of scope.
+ std::ostream& stream();
+
+ // The routine that performs the actual logging.
+ static void LogLine(const char* file, unsigned int line, LogSeverity severity, const char* msg);
private:
- static void LogLine(const LogMessageData& data, const char*);
-
const std::unique_ptr<LogMessageData> data_;
- friend void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context);
- friend class Mutex;
DISALLOW_COPY_AND_ASSIGN(LogMessage);
};
-// 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;
-}
-
-template<typename T>
-class ConstDumpable {
- public:
- explicit ConstDumpable(const T& value) : value_(value) {
- }
-
- void Dump(std::ostream& os) const {
- value_.Dump(os);
- }
-
- private:
- const T& value_;
-
- DISALLOW_COPY_AND_ASSIGN(ConstDumpable);
-};
-
-template<typename T>
-std::ostream& operator<<(std::ostream& os, const ConstDumpable<T>& rhs) {
- rhs.Dump(os);
- return os;
-}
-
-// Helps you use operator<< in a const char*-like context such as our various 'F' methods with
-// format strings.
-template<typename T>
-class ToStr {
- public:
- explicit ToStr(const T& value) {
- std::ostringstream os;
- os << value;
- s_ = os.str();
- }
-
- const char* c_str() const {
- return s_.c_str();
- }
-
- const std::string& str() const {
- return s_;
- }
-
- private:
- std::string s_;
- DISALLOW_COPY_AND_ASSIGN(ToStr);
-};
-
-// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code,
-// and the "-verbose:" command line argument.
-struct LogVerbosity {
- bool class_linker; // Enabled with "-verbose:class".
- bool compiler;
- bool gc;
- bool heap;
- bool jdwp;
- bool jni;
- bool monitor;
- bool profiler;
- bool signals;
- bool startup;
- bool third_party_jni; // Enabled with "-verbose:third-party-jni".
- bool threads;
- bool verifier;
-};
-
-extern LogVerbosity gLogVerbosity;
-
-extern std::vector<std::string> gVerboseMethods;
-
-// Used on fatal exit. Prevents recursive aborts. Allows us to disable
-// some error checking to ensure fatal shutdown makes forward progress.
-extern unsigned int gAborting;
-
-extern void InitLogging(char* argv[]);
-
-extern const char* GetCmdLine();
-extern const char* ProgramInvocationName();
-extern const char* ProgramInvocationShortName();
-
} // namespace art
#endif // ART_RUNTIME_BASE_LOGGING_H_
diff --git a/runtime/base/logging_android.cc b/runtime/base/logging_android.cc
deleted file mode 100644
index 9b1ac58..0000000
--- a/runtime/base/logging_android.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "logging.h"
-
-#include <unistd.h>
-
-#include <iostream>
-
-#include "base/stringprintf.h"
-#include "cutils/log.h"
-
-namespace art {
-
-static const int kLogSeverityToAndroidLogPriority[] = {
- ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
- ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
-};
-
-void LogMessage::LogLine(const LogMessageData& data, const char* message) {
- const char* tag = ProgramInvocationShortName();
- int priority = kLogSeverityToAndroidLogPriority[data.severity];
- if (priority == ANDROID_LOG_FATAL) {
- LOG_PRI(priority, tag, "%s:%d] %s", data.file, data.line_number, message);
- } else {
- LOG_PRI(priority, tag, "%s", message);
- }
-}
-
-} // namespace art
diff --git a/runtime/base/logging_linux.cc b/runtime/base/logging_linux.cc
deleted file mode 100644
index 0399128..0000000
--- a/runtime/base/logging_linux.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "logging.h"
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cstdio>
-#include <cstring>
-#include <iostream>
-
-#include "base/stringprintf.h"
-#include "utils.h"
-
-namespace art {
-
-void LogMessage::LogLine(const LogMessageData& data, const char* message) {
- char severity = "VDIWEFF"[data.severity];
- fprintf(stderr, "%s %c %5d %5d %s:%d] %s\n",
- ProgramInvocationShortName(), severity, getpid(), ::art::GetTid(),
- data.file, data.line_number, message);
-}
-
-} // namespace art
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 70b6f7e..1d37349 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -428,9 +428,9 @@
if (this != Locks::logging_lock_) {
LOG(FATAL) << "Unexpected state_ in unlock " << cur_state << " for " << name_;
} else {
- LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1);
- LogMessage::LogLine(data, StringPrintf("Unexpected state_ %d in unlock for %s",
- cur_state, name_).c_str());
+ LogMessage::LogLine(__FILE__, __LINE__, INTERNAL_FATAL,
+ StringPrintf("Unexpected state_ %d in unlock for %s",
+ cur_state, name_).c_str());
_exit(1);
}
}
diff --git a/runtime/base/to_str.h b/runtime/base/to_str.h
new file mode 100644
index 0000000..6b1c84c
--- /dev/null
+++ b/runtime/base/to_str.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_BASE_TO_STR_H_
+#define ART_RUNTIME_BASE_TO_STR_H_
+
+#include <sstream>
+
+namespace art {
+
+// Helps you use operator<< in a const char*-like context such as our various 'F' methods with
+// format strings.
+template<typename T>
+class ToStr {
+ public:
+ explicit ToStr(const T& value) {
+ std::ostringstream os;
+ os << value;
+ s_ = os.str();
+ }
+
+ const char* c_str() const {
+ return s_.c_str();
+ }
+
+ const std::string& str() const {
+ return s_;
+ }
+
+ private:
+ std::string s_;
+ DISALLOW_COPY_AND_ASSIGN(ToStr);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_BASE_TO_STR_H_
diff --git a/runtime/base/unix_file/mapped_file.cc b/runtime/base/unix_file/mapped_file.cc
index 63927b1..77f4d02 100644
--- a/runtime/base/unix_file/mapped_file.cc
+++ b/runtime/base/unix_file/mapped_file.cc
@@ -42,7 +42,7 @@
struct stat st;
int result = TEMP_FAILURE_RETRY(fstat(Fd(), &st));
if (result == -1) {
- PLOG(WARNING) << "Failed to stat file '" << GetPath() << "'";
+ PLOG(::art::WARNING) << "Failed to stat file '" << GetPath() << "'";
return false;
}
file_size_ = st.st_size;
@@ -50,8 +50,8 @@
mapped_file_ = mmap(NULL, file_size_, PROT_READ, MAP_PRIVATE, Fd(), 0);
} while (mapped_file_ == MAP_FAILED && errno == EINTR);
if (mapped_file_ == MAP_FAILED) {
- PLOG(WARNING) << "Failed to mmap file '" << GetPath() << "' of size "
- << file_size_ << " bytes to memory";
+ PLOG(::art::WARNING) << "Failed to mmap file '" << GetPath() << "' of size "
+ << file_size_ << " bytes to memory";
return false;
}
map_mode_ = kMapReadOnly;
@@ -67,8 +67,7 @@
int result = TEMP_FAILURE_RETRY(ftruncate(Fd(), file_size));
#endif
if (result == -1) {
- PLOG(ERROR) << "Failed to truncate file '" << GetPath()
- << "' to size " << file_size;
+ PLOG(::art::ERROR) << "Failed to truncate file '" << GetPath() << "' to size " << file_size;
return false;
}
file_size_ = file_size;
@@ -77,7 +76,7 @@
mmap(NULL, file_size_, PROT_READ | PROT_WRITE, MAP_SHARED, Fd(), 0);
} while (mapped_file_ == MAP_FAILED && errno == EINTR);
if (mapped_file_ == MAP_FAILED) {
- PLOG(WARNING) << "Failed to mmap file '" << GetPath() << "' of size "
+ PLOG(::art::WARNING) << "Failed to mmap file '" << GetPath() << "' of size "
<< file_size_ << " bytes to memory";
return false;
}
@@ -89,8 +88,7 @@
CHECK(IsMapped());
int result = TEMP_FAILURE_RETRY(munmap(mapped_file_, file_size_));
if (result == -1) {
- PLOG(WARNING) << "Failed unmap file '" << GetPath() << "' of size "
- << file_size_;
+ PLOG(::art::WARNING) << "Failed unmap file '" << GetPath() << "' of size " << file_size_;
return false;
} else {
mapped_file_ = NULL;