diff options
50 files changed, 505 insertions, 454 deletions
diff --git a/compiler/dex/compiler_ir.cc b/compiler/dex/compiler_ir.cc index 909c995c32..a2b3fe432f 100644 --- a/compiler/dex/compiler_ir.cc +++ b/compiler/dex/compiler_ir.cc @@ -16,6 +16,7 @@ #include "compiler_ir.h" +#include "base/dumpable.h" #include "backend.h" #include "frontend.h" #include "mir_graph.h" diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc index 2e21d052ec..3dc5655919 100644 --- a/compiler/dex/frontend.cc +++ b/compiler/dex/frontend.cc @@ -19,6 +19,7 @@ #include <cstdint> #include "backend.h" +#include "base/dumpable.h" #include "compiler.h" #include "compiler_internals.h" #include "driver/compiler_driver.h" @@ -134,15 +135,8 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, (cu.enable_debug & (1 << kDebugVerbose)); } - if (gVerboseMethods.size() != 0) { - cu.verbose = false; - for (size_t i = 0; i < gVerboseMethods.size(); ++i) { - if (PrettyMethod(method_idx, dex_file).find(gVerboseMethods[i]) - != std::string::npos) { - cu.verbose = true; - break; - } - } + if (driver.GetCompilerOptions().HasVerboseMethods()) { + cu.verbose = driver.GetCompilerOptions().IsVerboseMethod(PrettyMethod(method_idx, dex_file)); } if (cu.verbose) { diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index 3a50bfdb83..fb7aeb9b06 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -17,9 +17,14 @@ #ifndef ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_ #define ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_ +#include <string> +#include <vector> + +#include "base/macros.h" + namespace art { -class CompilerOptions { +class CompilerOptions FINAL { public: enum CompilerFilter { kVerifyNone, // Skip verification and compile nothing except JNI stubs. @@ -60,11 +65,12 @@ class CompilerOptions { implicit_null_checks_(false), implicit_so_checks_(false), implicit_suspend_checks_(false), - compile_pic_(false) + compile_pic_(false), #ifdef ART_SEA_IR_MODE - , sea_ir_mode_(false) + sea_ir_mode_(false), #endif - {} + verbose_methods_(nullptr) { + } CompilerOptions(CompilerFilter compiler_filter, size_t huge_method_threshold, @@ -79,10 +85,11 @@ class CompilerOptions { bool implicit_null_checks, bool implicit_so_checks, bool implicit_suspend_checks, - bool compile_pic + bool compile_pic, #ifdef ART_SEA_IR_MODE - , bool sea_ir_mode + bool sea_ir_mode, #endif + const std::vector<std::string>* verbose_methods ) : // NOLINT(whitespace/parens) compiler_filter_(compiler_filter), huge_method_threshold_(huge_method_threshold), @@ -97,11 +104,12 @@ class CompilerOptions { implicit_null_checks_(implicit_null_checks), implicit_so_checks_(implicit_so_checks), implicit_suspend_checks_(implicit_suspend_checks), - compile_pic_(compile_pic) + compile_pic_(compile_pic), #ifdef ART_SEA_IR_MODE - , sea_ir_mode_(sea_ir_mode) + sea_ir_mode_(sea_ir_mode), #endif - {} + verbose_methods_(verbose_methods) { + } CompilerFilter GetCompilerFilter() const { return compiler_filter_; @@ -168,28 +176,18 @@ class CompilerOptions { return implicit_null_checks_; } - void SetImplicitNullChecks(bool new_val) { - implicit_null_checks_ = new_val; - } - bool GetImplicitStackOverflowChecks() const { return implicit_so_checks_; } - void SetImplicitStackOverflowChecks(bool new_val) { - implicit_so_checks_ = new_val; - } - bool GetImplicitSuspendChecks() const { return implicit_suspend_checks_; } - void SetImplicitSuspendChecks(bool new_val) { - implicit_suspend_checks_ = new_val; - } - #ifdef ART_SEA_IR_MODE - bool GetSeaIrMode(); + bool GetSeaIrMode() const { + return sea_ir_mode_; + } #endif bool GetGenerateGDBInformation() const { @@ -205,25 +203,44 @@ class CompilerOptions { return compile_pic_; } + bool HasVerboseMethods() const { + return verbose_methods_ != nullptr && !verbose_methods_->empty(); + } + + bool IsVerboseMethod(const std::string& pretty_method) const { + for (const std::string& cur_method : *verbose_methods_) { + if (pretty_method.find(cur_method) != std::string::npos) { + return true; + } + } + return false; + } + private: CompilerFilter compiler_filter_; - size_t huge_method_threshold_; - size_t large_method_threshold_; - size_t small_method_threshold_; - size_t tiny_method_threshold_; - size_t num_dex_methods_threshold_; - bool generate_gdb_information_; - bool include_patch_information_; + const size_t huge_method_threshold_; + const size_t large_method_threshold_; + const size_t small_method_threshold_; + const size_t tiny_method_threshold_; + const size_t num_dex_methods_threshold_; + const bool generate_gdb_information_; + const bool include_patch_information_; // When using a profile file only the top K% of the profiled samples will be compiled. - double top_k_profile_threshold_; - bool include_debug_symbols_; - bool implicit_null_checks_; - bool implicit_so_checks_; - bool implicit_suspend_checks_; - bool compile_pic_; + const double top_k_profile_threshold_; + const bool include_debug_symbols_; + const bool implicit_null_checks_; + const bool implicit_so_checks_; + const bool implicit_suspend_checks_; + const bool compile_pic_; + #ifdef ART_SEA_IR_MODE - bool sea_ir_mode_; + const bool sea_ir_mode_; #endif + + // Vector of methods to have verbose output enabled for. + const std::vector<std::string>* const verbose_methods_; + + DISALLOW_COPY_AND_ASSIGN(CompilerOptions); }; } // namespace art diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h index db3130678a..badf21d946 100644 --- a/compiler/optimizing/graph_checker.h +++ b/compiler/optimizing/graph_checker.h @@ -53,7 +53,7 @@ class GraphChecker : public HGraphVisitor { } // Print detected errors on output stream `os`. - void Dump(std::ostream& os) { + void Dump(std::ostream& os) const { for (size_t i = 0, e = errors_.Size(); i < e; ++i) { os << dump_prefix_ << errors_.Get(i) << std::endl; } @@ -68,7 +68,7 @@ class GraphChecker : public HGraphVisitor { private: // String displayed before dumped errors. - const char* dump_prefix_; + const char* const dump_prefix_; DISALLOW_COPY_AND_ASSIGN(GraphChecker); }; diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc index 33dc040e76..ea98186d11 100644 --- a/compiler/optimizing/optimization.cc +++ b/compiler/optimizing/optimization.cc @@ -16,6 +16,7 @@ #include "optimization.h" +#include "base/dumpable.h" #include "graph_checker.h" namespace art { diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc index fc65f97f69..f95c4a47e3 100644 --- a/compiler/optimizing/register_allocator.cc +++ b/compiler/optimizing/register_allocator.cc @@ -16,6 +16,8 @@ #include "register_allocator.h" +#include <sstream> + #include "base/bit_vector-inl.h" #include "code_generator.h" #include "ssa_liveness_analysis.h" diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 326fa729b2..977774043c 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -30,6 +30,7 @@ #include <sys/utsname.h> #endif +#include "base/dumpable.h" #include "base/stl_util.h" #include "base/stringpiece.h" #include "base/timing_logger.h" @@ -832,6 +833,7 @@ static int dex2oat(int argc, char** argv) { int small_method_threshold = CompilerOptions::kDefaultSmallMethodThreshold; int tiny_method_threshold = CompilerOptions::kDefaultTinyMethodThreshold; int num_dex_methods_threshold = CompilerOptions::kDefaultNumDexMethodsThreshold; + std::vector<std::string> verbose_methods; // Initialize ISA and ISA features to default values. InstructionSet instruction_set = kRuntimeISA; @@ -1058,6 +1060,11 @@ static int dex2oat(int argc, char** argv) { include_patch_information = true; } else if (option == "--no-include-patch-information") { include_patch_information = false; + } else if (option.starts_with("--verbose-methods=")) { + // TODO: rather than switch off compiler logging, make all VLOG(compiler) messages conditional + // on having verbost methods. + gLogVerbosity.compiler = false; + Split(option.substr(strlen("--verbose-methods=")).ToString(), ',', &verbose_methods); } else { Usage("Unknown argument %s", option.data()); } @@ -1213,24 +1220,25 @@ static int dex2oat(int argc, char** argv) { PassDriverMEOpts::PrintPassOptions(); } - std::unique_ptr<CompilerOptions> compiler_options(new CompilerOptions(compiler_filter, - huge_method_threshold, - large_method_threshold, - small_method_threshold, - tiny_method_threshold, - num_dex_methods_threshold, - generate_gdb_information, - include_patch_information, - top_k_profile_threshold, - include_debug_symbols, - implicit_null_checks, - implicit_so_checks, - implicit_suspend_checks, - compile_pic + std::unique_ptr<CompilerOptions> compiler_options( + new CompilerOptions(compiler_filter, + huge_method_threshold, + large_method_threshold, + small_method_threshold, + tiny_method_threshold, + num_dex_methods_threshold, + generate_gdb_information, + include_patch_information, + top_k_profile_threshold, + include_debug_symbols, + implicit_null_checks, + implicit_so_checks, + implicit_suspend_checks, + compile_pic, #ifdef ART_SEA_IR_MODE - , compiler_options.sea_ir_ = - true; + true, #endif + verbose_methods.empty() ? nullptr : &verbose_methods )); // NOLINT(whitespace/parens) // Done with usage checks, enable watchdog if requested diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc index ac883fe4e3..9caae9c48b 100644 --- a/disassembler/disassembler_arm.cc +++ b/disassembler/disassembler_arm.cc @@ -19,6 +19,7 @@ #include <inttypes.h> #include <iostream> +#include <sstream> #include "base/logging.h" #include "base/stringprintf.h" diff --git a/disassembler/disassembler_mips.cc b/disassembler/disassembler_mips.cc index bd5fac7377..c06492a3fe 100644 --- a/disassembler/disassembler_mips.cc +++ b/disassembler/disassembler_mips.cc @@ -17,6 +17,7 @@ #include "disassembler_mips.h" #include <iostream> +#include <sstream> #include "base/logging.h" #include "base/stringprintf.h" diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc index 63a74c7240..ce14520225 100644 --- a/disassembler/disassembler_x86.cc +++ b/disassembler/disassembler_x86.cc @@ -17,6 +17,7 @@ #include "disassembler_x86.h" #include <iostream> +#include <sstream> #include "base/logging.h" #include "base/stringprintf.h" diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index c0c96e5ac3..8e5af53e66 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -24,6 +24,7 @@ #include <string> #include <vector> +#include "base/dumpable.h" #include "base/scoped_flock.h" #include "base/stringpiece.h" #include "base/stringprintf.h" diff --git a/runtime/Android.mk b/runtime/Android.mk index d9b41397ae..0ef0fefd61 100644 --- a/runtime/Android.mk +++ b/runtime/Android.mk @@ -209,7 +209,6 @@ LIBART_HOST_LDFLAGS := LIBART_TARGET_SRC_FILES := \ $(LIBART_COMMON_SRC_FILES) \ - base/logging_android.cc \ jdwp/jdwp_adb.cc \ monitor_android.cc \ runtime_android.cc \ @@ -282,7 +281,6 @@ endif # TARGET_ARCH != mips64 LIBART_HOST_SRC_FILES := \ $(LIBART_COMMON_SRC_FILES) \ - base/logging_linux.cc \ monitor_linux.cc \ runtime_linux.cc \ thread_linux.cc @@ -477,7 +475,7 @@ $$(ENUM_OPERATOR_OUT_GEN): $$(GENERATED_SRC_DIR)/%_operator_out.cc : $(LOCAL_PAT endif endif LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk -# LOCAL_ADDITIONAL_DEPENDENCIES += $$(LOCAL_PATH)/Android.mk + LOCAL_ADDITIONAL_DEPENDENCIES += $$(LOCAL_PATH)/Android.mk ifeq ($$(art_target_or_host),target) LOCAL_MODULE_TARGET_ARCH := $$(ART_TARGET_SUPPORTED_ARCH) diff --git a/runtime/base/bit_vector.cc b/runtime/base/bit_vector.cc index 3d2f0deac5..1e0be3a433 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 0000000000..3c316cc015 --- /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 5af597b89b..46c3538ca3 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 @@ const char* ProgramInvocationShortName() { : "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 @@ void InitLogging(char* argv[]) { // 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 @@ void InitLogging(char* argv[]) { } } -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 cf3e763f1e..5e8e994020 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) : - -#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) + (UNLIKELY(!(x))) ? (LOG(::art::FATAL) << "Check failed: " << #x out, dummy) : -#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 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 { +#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 +// 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 @@ struct EagerEvaluator { 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(const signed char*, signed char*); 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); -} - -// 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); -}; +// Data for the log message, not stored in LogMessage to avoid increasing the stack size. +class 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(); - private: - static void LogLine(const LogMessageData& data, const char*); + // The routine that performs the actual logging. + static void LogLine(const char* file, unsigned int line, LogSeverity severity, const char* msg); + private: 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 9b1ac58461..0000000000 --- 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/mutex.cc b/runtime/base/mutex.cc index 70b6f7e295..1d373497eb 100644 --- a/runtime/base/mutex.cc +++ b/runtime/base/mutex.cc @@ -428,9 +428,9 @@ void Mutex::ExclusiveUnlock(Thread* self) { 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/logging_linux.cc b/runtime/base/to_str.h index 0399128d65..6b1c84c411 100644 --- a/runtime/base/logging_linux.cc +++ b/runtime/base/to_str.h @@ -14,25 +14,37 @@ * limitations under the License. */ -#include "logging.h" +#ifndef ART_RUNTIME_BASE_TO_STR_H_ +#define ART_RUNTIME_BASE_TO_STR_H_ -#include <sys/types.h> -#include <unistd.h> +#include <sstream> -#include <cstdio> -#include <cstring> -#include <iostream> +namespace art { -#include "base/stringprintf.h" -#include "utils.h" +// 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(); + } -namespace art { + const char* c_str() const { + return s_.c_str(); + } -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); -} + 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 63927b1216..77f4d020a9 100644 --- a/runtime/base/unix_file/mapped_file.cc +++ b/runtime/base/unix_file/mapped_file.cc @@ -42,7 +42,7 @@ bool MappedFile::MapReadOnly() { 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 @@ bool MappedFile::MapReadOnly() { 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 @@ bool MappedFile::MapReadWrite(int64_t file_size) { 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 @@ bool MappedFile::MapReadWrite(int64_t file_size) { 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 @@ bool MappedFile::Unmap() { 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; diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index fec1824a9e..b2df09136d 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -20,6 +20,7 @@ #include <zlib.h> #include "base/logging.h" +#include "base/to_str.h" #include "class_linker.h" #include "class_linker-inl.h" #include "dex_file-inl.h" diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index ea3da648fc..6e3ebc24d8 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -44,7 +44,7 @@ int main(int argc, char **argv) { art::InitLogging(argv); - LOG(INFO) << "Running main() from common_runtime_test.cc..."; + LOG(::art::INFO) << "Running main() from common_runtime_test.cc..."; testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc index f408386617..78cbe58416 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -23,7 +23,9 @@ #include <string.h> #include <sys/file.h> #include <sys/stat.h> + #include <memory> +#include <sstream> #include "base/logging.h" #include "base/stringprintf.h" diff --git a/runtime/dex_instruction.cc b/runtime/dex_instruction.cc index 7e775f4ed3..af38433abc 100644 --- a/runtime/dex_instruction.cc +++ b/runtime/dex_instruction.cc @@ -19,6 +19,7 @@ #include <inttypes.h> #include <iomanip> +#include <sstream> #include "base/stringprintf.h" #include "dex_file-inl.h" diff --git a/runtime/dex_method_iterator_test.cc b/runtime/dex_method_iterator_test.cc index b8f180b46f..b2b7138080 100644 --- a/runtime/dex_method_iterator_test.cc +++ b/runtime/dex_method_iterator_test.cc @@ -39,7 +39,7 @@ TEST_F(DexMethodIteratorTest, Basic) { InvokeType invoke_type = it.GetInvokeType(); uint32_t method_idx = it.GetMemberIndex(); if (false) { - LG << invoke_type << " " << PrettyMethod(method_idx, dex_file); + LOG(INFO) << invoke_type << " " << PrettyMethod(method_idx, dex_file); } it.Next(); } diff --git a/runtime/elf_utils.h b/runtime/elf_utils.h index 676cd522e6..7b00bada47 100644 --- a/runtime/elf_utils.h +++ b/runtime/elf_utils.h @@ -24,6 +24,8 @@ #include "base/logging.h" +namespace art { + // Architecture dependent flags for the ELF header. #define EF_ARM_EABI_VER5 0x05000000 #define EF_MIPS_ABI_O32 0x00001000 @@ -163,4 +165,6 @@ static inline bool IsDynamicSectionPointer(Elf32_Word d_tag, Elf32_Word e_machin } } +} // namespace art + #endif // ART_RUNTIME_ELF_UTILS_H_ diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc index 6b3e9dc98a..f78273f24c 100644 --- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc @@ -52,7 +52,7 @@ extern "C" TwoWordReturn artInstrumentationMethodExitFromCode(Thread* self, uint64_t fpr_result) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Compute address of return PC and sanity check that it currently holds 0. - uint32_t return_pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, Runtime::kRefsOnly); + size_t return_pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, Runtime::kRefsOnly); uintptr_t* return_pc = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(sp) + return_pc_offset); CHECK_EQ(*return_pc, 0U); diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc index c2395352bc..c1276b5bf2 100644 --- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc @@ -15,6 +15,7 @@ */ #include "entrypoints/entrypoint_utils-inl.h" +#include "mirror/art_method-inl.h" #include "mirror/object-inl.h" #include "thread-inl.h" #include "verify_object-inl.h" diff --git a/runtime/gc/allocator/dlmalloc.cc b/runtime/gc/allocator/dlmalloc.cc index a6a3ee7a57..fbeba7f447 100644 --- a/runtime/gc/allocator/dlmalloc.cc +++ b/runtime/gc/allocator/dlmalloc.cc @@ -39,11 +39,11 @@ static void art_heap_usage_error(const char* function, void* p); static void art_heap_corruption(const char* function) { - LOG(FATAL) << "Corrupt heap detected in: " << function; + LOG(::art::FATAL) << "Corrupt heap detected in: " << function; } static void art_heap_usage_error(const char* function, void* p) { - LOG(FATAL) << "Incorrect use of function '" << function << "' argument " << p << " not expected"; + LOG(::art::FATAL) << "Incorrect use of function '" << function << "' argument " << p << " not expected"; } #include "globals.h" @@ -63,7 +63,7 @@ extern "C" void DlmallocMadviseCallback(void* start, void* end, size_t used_byte int rc = madvise(start, length, MADV_DONTNEED); if (UNLIKELY(rc != 0)) { errno = rc; - PLOG(FATAL) << "madvise failed during heap trimming"; + PLOG(::art::FATAL) << "madvise failed during heap trimming"; } size_t* reclaimed = reinterpret_cast<size_t*>(arg); *reclaimed += length; diff --git a/runtime/gc/allocator/rosalloc.cc b/runtime/gc/allocator/rosalloc.cc index a3da532ec8..804c98a99f 100644 --- a/runtime/gc/allocator/rosalloc.cc +++ b/runtime/gc/allocator/rosalloc.cc @@ -24,6 +24,7 @@ #include <map> #include <list> +#include <sstream> #include <vector> namespace art { diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc index 07b61e6cf0..4148e9c0b9 100644 --- a/runtime/gc/collector/garbage_collector.cc +++ b/runtime/gc/collector/garbage_collector.cc @@ -18,6 +18,7 @@ #include "garbage_collector.h" +#include "base/dumpable.h" #include "base/histogram-inl.h" #include "base/logging.h" #include "base/mutex-inl.h" @@ -188,7 +189,7 @@ void GarbageCollector::DumpPerformanceInfo(std::ostream& os) { if (iterations == 0) { return; } - os << ConstDumpable<CumulativeLogger>(logger); + os << Dumpable<CumulativeLogger>(logger); const uint64_t total_ns = logger.GetTotalNs(); double seconds = NsToMs(logger.GetTotalNs()) / 1000.0; const uint64_t freed_bytes = GetTotalFreedBytes(); diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc index 9459a3b829..e141b6f4ab 100644 --- a/runtime/gc/collector/semi_space.cc +++ b/runtime/gc/collector/semi_space.cc @@ -16,9 +16,10 @@ #include "semi_space-inl.h" +#include <climits> #include <functional> #include <numeric> -#include <climits> +#include <sstream> #include <vector> #include "base/logging.h" diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index b9d69d55c7..c2baa29f61 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -24,6 +24,7 @@ #include <vector> #include "base/allocator.h" +#include "base/dumpable.h" #include "base/histogram-inl.h" #include "base/stl_util.h" #include "common_throws.h" @@ -2178,7 +2179,7 @@ collector::GcType Heap::CollectGarbageInternal(collector::GcType gc_type, GcCaus << percent_free << "% free, " << PrettySize(current_heap_size) << "/" << PrettySize(total_memory) << ", " << "paused " << pause_string.str() << " total " << PrettyDuration((duration / 1000) * 1000); - VLOG(heap) << ConstDumpable<TimingLogger>(*current_gc_iteration_.GetTimings()); + VLOG(heap) << Dumpable<TimingLogger>(*current_gc_iteration_.GetTimings()); } FinishGC(self, gc_type); // Inform DDMS that a GC completed. diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 39d82cc8a3..d4790385d1 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -21,6 +21,7 @@ #include <random> +#include "base/macros.h" #include "base/stl_util.h" #include "base/unix_file/fd_file.h" #include "base/scoped_flock.h" diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index adbece0e18..f981522161 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -18,12 +18,15 @@ #include <sys/uio.h> +#include <sstream> + #include "arch/context.h" #include "atomic.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" #include "debugger.h" #include "dex_file-inl.h" +#include "entrypoints/quick/quick_entrypoints.h" #include "entrypoints/quick/quick_alloc_entrypoints.h" #include "entrypoints/runtime_asm_entrypoints.h" #include "gc_root-inl.h" @@ -34,9 +37,6 @@ #include "mirror/object_array-inl.h" #include "mirror/object-inl.h" #include "nth_caller_visitor.h" -#if !defined(ART_USE_PORTABLE_COMPILER) -#include "entrypoints/quick/quick_entrypoints.h" -#endif #include "os.h" #include "scoped_thread_state_change.h" #include "thread.h" diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index a8345ad579..f8858d09fe 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -21,6 +21,8 @@ #include <math.h> +#include <sstream> + #include "base/logging.h" #include "class_linker-inl.h" #include "common_throws.h" diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index fed8bf07be..19e03d8f82 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -18,6 +18,7 @@ #include <dlfcn.h> +#include "base/dumpable.h" #include "base/mutex.h" #include "base/stl_util.h" #include "check_jni.h" diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 70754f28ec..ad06b85f36 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -2705,7 +2705,7 @@ std::ostream& operator<<(std::ostream& os, const jobjectRefType& rhs) { os << "JNIWeakGlobalRefType"; return os; default: - LOG(FATAL) << "jobjectRefType[" << static_cast<int>(rhs) << "]"; - return os; + LOG(::art::FATAL) << "jobjectRefType[" << static_cast<int>(rhs) << "]"; + UNREACHABLE(); } } diff --git a/runtime/log_severity.h b/runtime/log_severity.h deleted file mode 100644 index 31682dfeee..0000000000 --- a/runtime/log_severity.h +++ /dev/null @@ -1,25 +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. - */ - -#ifndef ART_RUNTIME_LOG_SEVERITY_H_ -#define ART_RUNTIME_LOG_SEVERITY_H_ - -typedef int LogSeverity; - -const int VERBOSE = 0, DEBUG = 1, INFO = 2, WARNING = 3, ERROR = 4, FATAL = 5; -const int INTERNAL_FATAL = 6; // For Runtime::Abort. - -#endif // ART_RUNTIME_LOG_SEVERITY_H_ diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc index 3144ce1643..c1184716b1 100644 --- a/runtime/mem_map.cc +++ b/runtime/mem_map.cc @@ -15,11 +15,12 @@ */ #include "mem_map.h" -#include "thread-inl.h" -#include <inttypes.h> #include <backtrace/BacktraceMap.h> +#include <inttypes.h> + #include <memory> +#include <sstream> // See CreateStartPos below. #ifdef __BIONIC__ @@ -28,6 +29,7 @@ #include "base/stringprintf.h" #include "ScopedFd.h" +#include "thread-inl.h" #include "utils.h" #define USE_ASHMEM 1 diff --git a/runtime/native/scoped_fast_native_object_access.h b/runtime/native/scoped_fast_native_object_access.h index 606d62d8ce..dfabff5f6a 100644 --- a/runtime/native/scoped_fast_native_object_access.h +++ b/runtime/native/scoped_fast_native_object_access.h @@ -17,7 +17,7 @@ #ifndef ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_ #define ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_ -#include "mirror/art_method.h" +#include "mirror/art_method-inl.h" #include "scoped_thread_state_change.h" namespace art { diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index dcca9d3164..6b64c257df 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -16,6 +16,8 @@ #include "parsed_options.h" +#include <sstream> + #ifdef HAVE_ANDROID_OS #include "cutils/properties.h" #endif @@ -534,9 +536,6 @@ bool ParsedOptions::Parse(const RuntimeOptions& options, bool ignore_unrecognize return false; } } - } else if (StartsWith(option, "-verbose-methods:")) { - gLogVerbosity.compiler = false; - Split(option.substr(strlen("-verbose-methods:")), ',', &gVerboseMethods); } else if (StartsWith(option, "-Xlockprofthreshold:")) { if (!ParseUnsignedInteger(option, ':', &lock_profiling_threshold_)) { return false; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index c16e9edde9..da513080d5 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -45,6 +45,7 @@ #include "arch/x86_64/registers_x86_64.h" #include "asm_support.h" #include "atomic.h" +#include "base/dumpable.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" #include "debugger.h" @@ -204,7 +205,7 @@ Runtime::~Runtime() { } struct AbortState { - void Dump(std::ostream& os) { + void Dump(std::ostream& os) const { if (gAborting > 1) { os << "Runtime aborting --- recursively, so no thread-specific detail!\n"; return; @@ -235,7 +236,7 @@ struct AbortState { } // No thread-safety analysis as we do explicitly test for holding the mutator lock. - void DumpThread(std::ostream& os, Thread* self) NO_THREAD_SAFETY_ANALYSIS { + void DumpThread(std::ostream& os, Thread* self) const NO_THREAD_SAFETY_ANALYSIS { DCHECK(Locks::mutator_lock_->IsExclusiveHeld(self) || Locks::mutator_lock_->IsSharedHeld(self)); self->Dump(os); if (self->IsExceptionPending()) { @@ -247,7 +248,7 @@ struct AbortState { } } - void DumpAllThreads(std::ostream& os, Thread* self) { + void DumpAllThreads(std::ostream& os, Thread* self) const { Runtime* runtime = Runtime::Current(); if (runtime != nullptr) { ThreadList* thread_list = runtime->GetThreadList(); diff --git a/runtime/runtime_android.cc b/runtime/runtime_android.cc index 079d7e5900..33600ddba5 100644 --- a/runtime/runtime_android.cc +++ b/runtime/runtime_android.cc @@ -32,13 +32,12 @@ static constexpr bool kUseSignalHandler = false; struct sigaction old_action; void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context) { - static bool handlingUnexpectedSignal = false; - if (handlingUnexpectedSignal) { - LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1); - LogMessage::LogLine(data, "HandleUnexpectedSignal reentered\n"); + static bool handling_unexpected_signal = false; + if (handling_unexpected_signal) { + LogMessage::LogLine(__FILE__, __LINE__, INTERNAL_FATAL, "HandleUnexpectedSignal reentered\n"); _exit(1); } - handlingUnexpectedSignal = true; + handling_unexpected_signal = true; gAborting++; // set before taking any locks MutexLock mu(Thread::Current(), *Locks::unexpected_signal_lock_); diff --git a/runtime/runtime_linux.cc b/runtime/runtime_linux.cc index 46ee27405f..1de035c0d5 100644 --- a/runtime/runtime_linux.cc +++ b/runtime/runtime_linux.cc @@ -21,6 +21,9 @@ #include <sys/utsname.h> #include <inttypes.h> +#include <sstream> + +#include "base/dumpable.h" #include "base/logging.h" #include "base/mutex.h" #include "base/stringprintf.h" @@ -32,13 +35,13 @@ namespace art { static constexpr bool kDumpHeapObjectOnSigsevg = false; struct Backtrace { - void Dump(std::ostream& os) { + void Dump(std::ostream& os) const { DumpNativeStack(os, GetTid(), "\t"); } }; struct OsInfo { - void Dump(std::ostream& os) { + void Dump(std::ostream& os) const { utsname info; uname(&info); // Linux 2.6.38.8-gg784 (x86_64) @@ -132,9 +135,11 @@ static const char* GetSignalCodeName(int signal_number, int signal_code) { } struct UContext { - explicit UContext(void* raw_context) : context(reinterpret_cast<ucontext_t*>(raw_context)->uc_mcontext) {} + explicit UContext(void* raw_context) : + context(reinterpret_cast<ucontext_t*>(raw_context)->uc_mcontext) { + } - void Dump(std::ostream& os) { + void Dump(std::ostream& os) const { // TODO: support non-x86 hosts (not urgent because this code doesn't run on targets). #if defined(__APPLE__) && defined(__i386__) DumpRegister32(os, "eax", context->__ss.__eax); @@ -228,15 +233,15 @@ struct UContext { #endif } - void DumpRegister32(std::ostream& os, const char* name, uint32_t value) { + void DumpRegister32(std::ostream& os, const char* name, uint32_t value) const { os << StringPrintf(" %6s: 0x%08x", name, value); } - void DumpRegister64(std::ostream& os, const char* name, uint64_t value) { + void DumpRegister64(std::ostream& os, const char* name, uint64_t value) const { os << StringPrintf(" %6s: 0x%016" PRIx64, name, value); } - void DumpX86Flags(std::ostream& os, uint32_t flags) { + void DumpX86Flags(std::ostream& os, uint32_t flags) const { os << " ["; if ((flags & (1 << 0)) != 0) { os << " CF"; @@ -274,8 +279,7 @@ struct UContext { void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context) { static bool handlingUnexpectedSignal = false; if (handlingUnexpectedSignal) { - LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1); - LogMessage::LogLine(data, "HandleUnexpectedSignal reentered\n"); + LogMessage::LogLine(__FILE__, __LINE__, INTERNAL_FATAL, "HandleUnexpectedSignal reentered\n"); _exit(1); } handlingUnexpectedSignal = true; diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc index 336340eca9..6d6783678f 100644 --- a/runtime/signal_catcher.cc +++ b/runtime/signal_catcher.cc @@ -25,6 +25,8 @@ #include <sys/types.h> #include <unistd.h> +#include <sstream> + #include "base/unix_file/fd_file.h" #include "class_linker.h" #include "gc/heap.h" diff --git a/runtime/thread.cc b/runtime/thread.cc index 83c4e03650..32d3129d37 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -29,9 +29,11 @@ #include <cerrno> #include <iostream> #include <list> +#include <sstream> #include "arch/context.h" #include "base/mutex.h" +#include "base/to_str.h" #include "class_linker-inl.h" #include "class_linker.h" #include "debugger.h" diff --git a/runtime/thread_linux.cc b/runtime/thread_linux.cc index 125405625b..0284364de7 100644 --- a/runtime/thread_linux.cc +++ b/runtime/thread_linux.cc @@ -16,6 +16,8 @@ #include "thread.h" +#include <signal.h> + namespace art { void Thread::SetNativePriority(int) { diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc index 646830acc6..6e189047fe 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc @@ -25,6 +25,8 @@ #include <sys/types.h> #include <unistd.h> +#include <sstream> + #include "base/mutex.h" #include "base/mutex-inl.h" #include "base/timing_logger.h" @@ -480,17 +482,18 @@ void ThreadList::Resume(Thread* thread, bool for_debugger) { VLOG(threads) << "Resume(" << reinterpret_cast<void*>(thread) << ") complete"; } -static void ThreadSuspendByPeerWarning(Thread* self, int level, const char* message, jobject peer) { +static void ThreadSuspendByPeerWarning(Thread* self, LogSeverity severity, const char* message, + jobject peer) { JNIEnvExt* env = self->GetJniEnv(); ScopedLocalRef<jstring> scoped_name_string(env, (jstring)env->GetObjectField(peer, WellKnownClasses::java_lang_Thread_name)); ScopedUtfChars scoped_name_chars(env, scoped_name_string.get()); if (scoped_name_chars.c_str() == NULL) { - LOG(level) << message << ": " << peer; + LOG(severity) << message << ": " << peer; env->ExceptionClear(); } else { - LOG(level) << message << ": " << peer << ":" << scoped_name_chars.c_str(); + LOG(severity) << message << ": " << peer << ":" << scoped_name_chars.c_str(); } } @@ -562,8 +565,9 @@ Thread* ThreadList::SuspendThreadByPeer(jobject peer, bool request_suspension, } } -static void ThreadSuspendByThreadIdWarning(int level, const char* message, uint32_t thread_id) { - LOG(level) << StringPrintf("%s: %d", message, thread_id); +static void ThreadSuspendByThreadIdWarning(LogSeverity severity, const char* message, + uint32_t thread_id) { + LOG(severity) << StringPrintf("%s: %d", message, thread_id); } Thread* ThreadList::SuspendThreadByThreadId(uint32_t thread_id, bool debug_suspension, diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 4a3c3ec549..fc3c8796f8 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -18,6 +18,8 @@ #include <stdlib.h> +#include <sstream> + #include "base/logging.h" #include "mirror/class.h" #include "ScopedLocalRef.h" |