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