blob: 94dd2c6f1d42c706129ec49ce7febf9b4db34376 [file] [log] [blame]
Elliott Hughes42ee1422011-09-06 12:33:32 -07001/*
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 */
Carl Shapiro6c21dc12011-06-20 15:20:52 -070016
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070017#ifndef ART_SRC_LOGGING_H_
18#define ART_SRC_LOGGING_H_
Carl Shapiro6c21dc12011-06-20 15:20:52 -070019
Elliott Hugheseb4f6142011-07-15 17:43:51 -070020#include <cerrno>
21#include <cstring>
Carl Shapiro6c21dc12011-06-20 15:20:52 -070022#include <iostream> // NOLINT
Elliott Hugheseb4f6142011-07-15 17:43:51 -070023#include <sstream>
24#include "log_severity.h"
25#include "macros.h"
Carl Shapiro6c21dc12011-06-20 15:20:52 -070026
27#define CHECK(x) \
Ian Rogerscaab8c42011-10-12 12:11:18 -070028 if (UNLIKELY(!(x))) \
Elliott Hughesf5a7a472011-10-07 14:31:02 -070029 ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
Elliott Hughes710a0cb2011-08-16 14:32:37 -070030 << "Check failed: " #x << " "
Elliott Hugheseb4f6142011-07-15 17:43:51 -070031
Elliott Hughes1f359b02011-07-17 14:27:17 -070032#define CHECK_OP(LHS, RHS, OP) \
Ian Rogerscaab8c42011-10-12 12:11:18 -070033 for (::art::EagerEvaluator<typeof(LHS), typeof(RHS)> _values(LHS, RHS); \
Elliott Hughes362f9bc2011-10-17 18:56:41 -070034 UNLIKELY(!(_values.lhs OP _values.rhs)); /* empty */) \
Elliott Hughesf5a7a472011-10-07 14:31:02 -070035 ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
36 << "Check failed: " << #LHS << " " << #OP << " " << #RHS \
37 << " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") "
Elliott Hughes1f359b02011-07-17 14:27:17 -070038
39#define CHECK_EQ(x, y) CHECK_OP(x, y, ==)
40#define CHECK_NE(x, y) CHECK_OP(x, y, !=)
41#define CHECK_LE(x, y) CHECK_OP(x, y, <=)
42#define CHECK_LT(x, y) CHECK_OP(x, y, <)
43#define CHECK_GE(x, y) CHECK_OP(x, y, >=)
44#define CHECK_GT(x, y) CHECK_OP(x, y, >)
Elliott Hugheseb4f6142011-07-15 17:43:51 -070045
46#define CHECK_STROP(s1, s2, sense) \
Ian Rogerscaab8c42011-10-12 12:11:18 -070047 if (UNLIKELY((strcmp(s1, s2) == 0) != sense)) \
Elliott Hughesf5a7a472011-10-07 14:31:02 -070048 LOG(FATAL) << "Check failed: " \
49 << "\"" << s1 << "\"" \
50 << (sense ? " == " : " != ") \
51 << "\"" << s2 << "\""
Carl Shapiro6c21dc12011-06-20 15:20:52 -070052
Elliott Hughes1f359b02011-07-17 14:27:17 -070053#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true)
54#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false)
55
Elliott Hughes8d768a92011-09-14 16:35:25 -070056#define CHECK_PTHREAD_CALL(call, args, what) \
57 do { \
58 int rc = call args; \
59 if (rc != 0) { \
60 errno = rc; \
61 PLOG(FATAL) << # call << " failed for " << what; \
62 } \
63 } while (false)
64
Carl Shapiro6c21dc12011-06-20 15:20:52 -070065#ifndef NDEBUG
66
67#define DCHECK(x) CHECK(x)
68#define DCHECK_EQ(x, y) CHECK_EQ(x, y)
69#define DCHECK_NE(x, y) CHECK_NE(x, y)
70#define DCHECK_LE(x, y) CHECK_LE(x, y)
71#define DCHECK_LT(x, y) CHECK_LT(x, y)
72#define DCHECK_GE(x, y) CHECK_GE(x, y)
73#define DCHECK_GT(x, y) CHECK_GT(x, y)
Elliott Hugheseb4f6142011-07-15 17:43:51 -070074#define DCHECK_STREQ(s1, s2) CHECK_STREQ(s1, s2)
75#define DCHECK_STRNE(s1, s2) CHECK_STRNE(s1, s2)
Carl Shapiro6c21dc12011-06-20 15:20:52 -070076
77#else // NDEBUG
78
79#define DCHECK(condition) \
80 while (false) \
81 CHECK(condition)
82
83#define DCHECK_EQ(val1, val2) \
84 while (false) \
85 CHECK_EQ(val1, val2)
86
87#define DCHECK_NE(val1, val2) \
88 while (false) \
89 CHECK_NE(val1, val2)
90
91#define DCHECK_LE(val1, val2) \
92 while (false) \
93 CHECK_LE(val1, val2)
94
95#define DCHECK_LT(val1, val2) \
96 while (false) \
97 CHECK_LT(val1, val2)
98
99#define DCHECK_GE(val1, val2) \
100 while (false) \
101 CHECK_GE(val1, val2)
102
103#define DCHECK_GT(val1, val2) \
104 while (false) \
105 CHECK_GT(val1, val2)
106
107#define DCHECK_STREQ(str1, str2) \
108 while (false) \
109 CHECK_STREQ(str1, str2)
110
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700111#define DCHECK_STRNE(str1, str2) \
112 while (false) \
113 CHECK_STRNE(str1, str2)
114
Carl Shapiro6c21dc12011-06-20 15:20:52 -0700115#endif
116
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700117#define LOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, -1).stream()
118#define PLOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, errno).stream()
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700119
Carl Shapiro6c21dc12011-06-20 15:20:52 -0700120#define LG LOG(INFO)
121
Elliott Hughes8d768a92011-09-14 16:35:25 -0700122#define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
Elliott Hughes53b61312011-08-12 18:28:20 -0700123
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800124#define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module)
125#define VLOG(module) if (VLOG_IS_ON(module)) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
126
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700127//
128// Implementation details beyond this point.
129//
130
131namespace art {
132
133template <typename LHS, typename RHS>
134struct EagerEvaluator {
135 EagerEvaluator(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) { }
136 LHS lhs;
137 RHS rhs;
138};
139
Elliott Hughesaa6a5882012-01-13 19:39:16 -0800140// We want char*s to be treated as pointers, not strings. If you want them treated like strings,
141// you'd need to use CHECK_STREQ and CHECK_STRNE anyway to compare the characters rather than their
142// addresses. We could express this more succinctly with std::remove_const, but this is quick and
143// easy to understand, and works before we have C++0x. We rely on signed/unsigned warnings to
144// protect you against combinations not explicitly listed below.
145#define EAGER_PTR_EVALUATOR(T1, T2) \
146 template <> struct EagerEvaluator<T1, T2> { \
147 EagerEvaluator(T1 lhs, T2 rhs) \
148 : lhs(reinterpret_cast<const void*>(lhs)), \
149 rhs(reinterpret_cast<const void*>(rhs)) { } \
150 const void* lhs; \
151 const void* rhs; \
152 }
153EAGER_PTR_EVALUATOR(const char*, const char*);
154EAGER_PTR_EVALUATOR(const char*, char*);
155EAGER_PTR_EVALUATOR(char*, const char*);
156EAGER_PTR_EVALUATOR(char*, char*);
157EAGER_PTR_EVALUATOR(const unsigned char*, const unsigned char*);
158EAGER_PTR_EVALUATOR(const unsigned char*, unsigned char*);
159EAGER_PTR_EVALUATOR(unsigned char*, const unsigned char*);
160EAGER_PTR_EVALUATOR(unsigned char*, unsigned char*);
161EAGER_PTR_EVALUATOR(const signed char*, const signed char*);
162EAGER_PTR_EVALUATOR(const signed char*, signed char*);
163EAGER_PTR_EVALUATOR(signed char*, const signed char*);
164EAGER_PTR_EVALUATOR(signed char*, signed char*);
165
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700166// This indirection greatly reduces the stack impact of having
167// lots of checks/logging in a function.
168struct LogMessageData {
169 public:
170 LogMessageData(int line, LogSeverity severity, int error)
171 : file(NULL),
172 line_number(line),
173 severity(severity),
174 error(error) {
175 }
176
177 std::ostringstream buffer;
178 const char* file;
179 int line_number;
180 LogSeverity severity;
181 int error;
182
183 private:
184 DISALLOW_COPY_AND_ASSIGN(LogMessageData);
185};
186
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700187class LogMessage {
188 public:
189 LogMessage(const char* file, int line, LogSeverity severity, int error);
190 ~LogMessage();
191 std::ostream& stream();
192
193 private:
194 void LogLine(const char*);
195
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700196 LogMessageData* data_;
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700197
198 DISALLOW_COPY_AND_ASSIGN(LogMessage);
199};
200
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700201// Prints a hex dump in this format:
202//
203// 01234560: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef
204// 01234568: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef
205class HexDump {
206 public:
207 HexDump(const void* address, size_t byte_count, bool show_actual_addresses = false);
208 void Dump(std::ostream& os) const;
209
210 private:
211 const void* address_;
212 size_t byte_count_;
213 bool show_actual_addresses_;
Elliott Hughes878820f2012-03-29 20:00:04 -0700214
215 // TODO: Remove the #if when Mac OS build server no longer uses GCC 4.2.*.
216#if GCC_VERSION >= 40300
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700217 DISALLOW_COPY_AND_ASSIGN(HexDump);
Elliott Hughes878820f2012-03-29 20:00:04 -0700218#endif
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700219};
220std::ostream& operator<<(std::ostream& os, const HexDump& rhs);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700221
Elliott Hughese0918552011-10-28 17:18:29 -0700222// A convenience to allow any class with a "Dump(std::ostream& os)" member function
223// but without an operator<< to be used as if it had an operator<<. Use like this:
224//
225// os << Dumpable<MyType>(my_type_instance);
226//
227template<typename T>
228class Dumpable {
229 public:
230 explicit Dumpable(T& value) : value_(value) {
231 }
232
233 void Dump(std::ostream& os) const {
234 value_.Dump(os);
235 }
236
237 private:
238 T& value_;
Shih-wei Liao24782c62012-01-08 12:46:11 -0800239
240// TODO: Remove the #if when Mac OS build server no longer uses GCC 4.2.*.
241#if GCC_VERSION >= 40300
Elliott Hughese0918552011-10-28 17:18:29 -0700242 DISALLOW_COPY_AND_ASSIGN(Dumpable);
Shih-wei Liao24782c62012-01-08 12:46:11 -0800243#endif
Elliott Hughese0918552011-10-28 17:18:29 -0700244};
245
246template<typename T>
247std::ostream& operator<<(std::ostream& os, const Dumpable<T>& rhs) {
248 rhs.Dump(os);
249 return os;
250}
251
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700252// Helps you use operator<< in a const char*-like context such as our various 'F' methods with
253// format strings.
254template<typename T>
255class ToStr {
256 public:
Elliott Hughes74847412012-06-20 18:10:21 -0700257 explicit ToStr(const T& value) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700258 std::ostringstream os;
259 os << value;
260 s_ = os.str();
261 }
262
263 const char* c_str() const {
264 return s_.c_str();
265 }
266
267 const std::string& str() const {
268 return s_;
269 }
270
271 private:
272 std::string s_;
273 DISALLOW_COPY_AND_ASSIGN(ToStr);
274};
275
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800276// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code,
277// and the "-verbose:" command line argument.
278struct LogVerbosity {
279 bool class_linker; // Enabled with "-verbose:class".
280 bool compiler;
281 bool heap;
282 bool gc;
283 bool jdwp;
284 bool jni;
285 bool monitor;
286 bool startup;
287 bool third_party_jni; // Enabled with "-verbose:third-party-jni".
288 bool threads;
289};
290
291extern LogVerbosity gLogVerbosity;
Elliott Hughes0d39c122012-06-06 16:41:17 -0700292extern void InitLogging(char* argv[]);
293
294extern const char* GetCmdLine();
295extern const char* ProgramInvocationName();
296extern const char* ProgramInvocationShortName();
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800297
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700298} // namespace art
299
Carl Shapiro6b6b5f02011-06-21 15:05:09 -0700300#endif // ART_SRC_LOGGING_H_