logging.h revision 4d466a8e4587422c989705dce3b2a19e7f0137f5
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_RUNTIME_BASE_LOGGING_H_ 18#define ART_RUNTIME_BASE_LOGGING_H_ 19 20#include <cerrno> 21#include <cstring> 22#include <iostream> // NOLINT 23#include <sstream> 24#include <signal.h> 25#include <vector> 26#include "base/macros.h" 27#include "log_severity.h" 28#include "UniquePtr.h" 29 30#define CHECK(x) \ 31 if (UNLIKELY(!(x))) \ 32 ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \ 33 << "Check failed: " #x << " " 34 35#define CHECK_OP(LHS, RHS, OP) \ 36 for (auto _values = ::art::MakeEagerEvaluator(LHS, RHS); \ 37 UNLIKELY(!(_values.lhs OP _values.rhs)); /* empty */) \ 38 ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \ 39 << "Check failed: " << #LHS << " " << #OP << " " << #RHS \ 40 << " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") " 41 42#define CHECK_EQ(x, y) CHECK_OP(x, y, ==) 43#define CHECK_NE(x, y) CHECK_OP(x, y, !=) 44#define CHECK_LE(x, y) CHECK_OP(x, y, <=) 45#define CHECK_LT(x, y) CHECK_OP(x, y, <) 46#define CHECK_GE(x, y) CHECK_OP(x, y, >=) 47#define CHECK_GT(x, y) CHECK_OP(x, y, >) 48 49#define CHECK_STROP(s1, s2, sense) \ 50 if (UNLIKELY((strcmp(s1, s2) == 0) != sense)) \ 51 LOG(FATAL) << "Check failed: " \ 52 << "\"" << s1 << "\"" \ 53 << (sense ? " == " : " != ") \ 54 << "\"" << s2 << "\"" 55 56#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true) 57#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false) 58 59#define CHECK_PTHREAD_CALL(call, args, what) \ 60 do { \ 61 int rc = call args; \ 62 if (rc != 0) { \ 63 errno = rc; \ 64 PLOG(FATAL) << # call << " failed for " << what; \ 65 } \ 66 } while (false) 67 68#ifndef NDEBUG 69 70#define DCHECK(x) CHECK(x) 71#define DCHECK_EQ(x, y) CHECK_EQ(x, y) 72#define DCHECK_NE(x, y) CHECK_NE(x, y) 73#define DCHECK_LE(x, y) CHECK_LE(x, y) 74#define DCHECK_LT(x, y) CHECK_LT(x, y) 75#define DCHECK_GE(x, y) CHECK_GE(x, y) 76#define DCHECK_GT(x, y) CHECK_GT(x, y) 77#define DCHECK_STREQ(s1, s2) CHECK_STREQ(s1, s2) 78#define DCHECK_STRNE(s1, s2) CHECK_STRNE(s1, s2) 79 80#else // NDEBUG 81 82#define DCHECK(condition) \ 83 while (false) \ 84 CHECK(condition) 85 86#define DCHECK_EQ(val1, val2) \ 87 while (false) \ 88 CHECK_EQ(val1, val2) 89 90#define DCHECK_NE(val1, val2) \ 91 while (false) \ 92 CHECK_NE(val1, val2) 93 94#define DCHECK_LE(val1, val2) \ 95 while (false) \ 96 CHECK_LE(val1, val2) 97 98#define DCHECK_LT(val1, val2) \ 99 while (false) \ 100 CHECK_LT(val1, val2) 101 102#define DCHECK_GE(val1, val2) \ 103 while (false) \ 104 CHECK_GE(val1, val2) 105 106#define DCHECK_GT(val1, val2) \ 107 while (false) \ 108 CHECK_GT(val1, val2) 109 110#define DCHECK_STREQ(str1, str2) \ 111 while (false) \ 112 CHECK_STREQ(str1, str2) 113 114#define DCHECK_STRNE(str1, str2) \ 115 while (false) \ 116 CHECK_STRNE(str1, str2) 117 118#endif 119 120#define LOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, -1).stream() 121#define PLOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, errno).stream() 122 123#define LG LOG(INFO) 124 125#define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented " 126 127#define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module) 128#define VLOG(module) if (VLOG_IS_ON(module)) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream() 129#define VLOG_STREAM(module) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream() 130 131// 132// Implementation details beyond this point. 133// 134 135namespace art { 136 137template <typename LHS, typename RHS> 138struct EagerEvaluator { 139 EagerEvaluator(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) { } 140 LHS lhs; 141 RHS rhs; 142}; 143 144// We want char*s to be treated as pointers, not strings. If you want them treated like strings, 145// you'd need to use CHECK_STREQ and CHECK_STRNE anyway to compare the characters rather than their 146// addresses. We could express this more succinctly with std::remove_const, but this is quick and 147// easy to understand, and works before we have C++0x. We rely on signed/unsigned warnings to 148// protect you against combinations not explicitly listed below. 149#define EAGER_PTR_EVALUATOR(T1, T2) \ 150 template <> struct EagerEvaluator<T1, T2> { \ 151 EagerEvaluator(T1 lhs, T2 rhs) \ 152 : lhs(reinterpret_cast<const void*>(lhs)), \ 153 rhs(reinterpret_cast<const void*>(rhs)) { } \ 154 const void* lhs; \ 155 const void* rhs; \ 156 } 157EAGER_PTR_EVALUATOR(const char*, const char*); 158EAGER_PTR_EVALUATOR(const char*, char*); 159EAGER_PTR_EVALUATOR(char*, const char*); 160EAGER_PTR_EVALUATOR(char*, char*); 161EAGER_PTR_EVALUATOR(const unsigned char*, const unsigned char*); 162EAGER_PTR_EVALUATOR(const unsigned char*, unsigned char*); 163EAGER_PTR_EVALUATOR(unsigned char*, const unsigned char*); 164EAGER_PTR_EVALUATOR(unsigned char*, unsigned char*); 165EAGER_PTR_EVALUATOR(const signed char*, const signed char*); 166EAGER_PTR_EVALUATOR(const signed char*, signed char*); 167EAGER_PTR_EVALUATOR(signed char*, const signed char*); 168EAGER_PTR_EVALUATOR(signed char*, signed char*); 169 170template <typename LHS, typename RHS> 171EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) { 172 return EagerEvaluator<LHS, RHS>(lhs, rhs); 173} 174 175// This indirection greatly reduces the stack impact of having 176// lots of checks/logging in a function. 177struct LogMessageData { 178 public: 179 LogMessageData(const char* file, int line, LogSeverity severity, int error); 180 std::ostringstream buffer; 181 const char* const file; 182 const int line_number; 183 const LogSeverity severity; 184 const int error; 185 186 private: 187 DISALLOW_COPY_AND_ASSIGN(LogMessageData); 188}; 189 190class LogMessage { 191 public: 192 LogMessage(const char* file, int line, LogSeverity severity, int error) 193 : data_(new LogMessageData(file, line, severity, error)) { 194 } 195 196 ~LogMessage(); // TODO: enable LOCKS_EXCLUDED(Locks::logging_lock_). 197 198 std::ostream& stream() { 199 return data_->buffer; 200 } 201 202 private: 203 static void LogLine(const LogMessageData& data, const char*); 204 205 const UniquePtr<LogMessageData> data_; 206 207 friend void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context); 208 friend class Mutex; 209 DISALLOW_COPY_AND_ASSIGN(LogMessage); 210}; 211 212// A convenience to allow any class with a "Dump(std::ostream& os)" member function 213// but without an operator<< to be used as if it had an operator<<. Use like this: 214// 215// os << Dumpable<MyType>(my_type_instance); 216// 217template<typename T> 218class Dumpable { 219 public: 220 explicit Dumpable(T& value) : value_(value) { 221 } 222 223 void Dump(std::ostream& os) const { 224 value_.Dump(os); 225 } 226 227 private: 228 T& value_; 229 230 DISALLOW_COPY_AND_ASSIGN(Dumpable); 231}; 232 233template<typename T> 234std::ostream& operator<<(std::ostream& os, const Dumpable<T>& rhs) { 235 rhs.Dump(os); 236 return os; 237} 238 239template<typename T> 240class ConstDumpable { 241 public: 242 explicit ConstDumpable(const T& value) : value_(value) { 243 } 244 245 void Dump(std::ostream& os) const { 246 value_.Dump(os); 247 } 248 249 private: 250 const T& value_; 251 252 DISALLOW_COPY_AND_ASSIGN(ConstDumpable); 253}; 254 255template<typename T> 256std::ostream& operator<<(std::ostream& os, const ConstDumpable<T>& rhs) { 257 rhs.Dump(os); 258 return os; 259} 260 261// Helps you use operator<< in a const char*-like context such as our various 'F' methods with 262// format strings. 263template<typename T> 264class ToStr { 265 public: 266 explicit ToStr(const T& value) { 267 std::ostringstream os; 268 os << value; 269 s_ = os.str(); 270 } 271 272 const char* c_str() const { 273 return s_.c_str(); 274 } 275 276 const std::string& str() const { 277 return s_; 278 } 279 280 private: 281 std::string s_; 282 DISALLOW_COPY_AND_ASSIGN(ToStr); 283}; 284 285// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code, 286// and the "-verbose:" command line argument. 287struct LogVerbosity { 288 bool class_linker; // Enabled with "-verbose:class". 289 bool compiler; 290 bool gc; 291 bool heap; 292 bool jdwp; 293 bool jni; 294 bool monitor; 295 bool profiler; 296 bool signals; 297 bool startup; 298 bool third_party_jni; // Enabled with "-verbose:third-party-jni". 299 bool threads; 300 bool verifier; 301}; 302 303extern LogVerbosity gLogVerbosity; 304 305extern std::vector<std::string> gVerboseMethods; 306 307// Used on fatal exit. Prevents recursive aborts. Allows us to disable 308// some error checking to ensure fatal shutdown makes forward progress. 309extern unsigned int gAborting; 310 311extern void InitLogging(char* argv[]); 312 313extern const char* GetCmdLine(); 314extern const char* ProgramInvocationName(); 315extern const char* ProgramInvocationShortName(); 316 317} // namespace art 318 319#endif // ART_RUNTIME_BASE_LOGGING_H_ 320