checks.h revision 8b112d2025046f85ef7f6be087c6129c872ebad2
1// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_CHECKS_H_
29#define V8_CHECKS_H_
30
31#include <string.h>
32
33#include "../include/v8stdint.h"
34extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
35
36// The FATAL, UNREACHABLE and UNIMPLEMENTED macros are useful during
37// development, but they should not be relied on in the final product.
38#ifdef DEBUG
39#define FATAL(msg)                              \
40  V8_Fatal(__FILE__, __LINE__, "%s", (msg))
41#define UNIMPLEMENTED()                         \
42  V8_Fatal(__FILE__, __LINE__, "unimplemented code")
43#define UNREACHABLE()                           \
44  V8_Fatal(__FILE__, __LINE__, "unreachable code")
45#else
46#define FATAL(msg)                              \
47  V8_Fatal("", 0, "%s", (msg))
48#define UNIMPLEMENTED()                         \
49  V8_Fatal("", 0, "unimplemented code")
50#define UNREACHABLE() ((void) 0)
51#endif
52
53
54// Used by the CHECK macro -- should not be called directly.
55static inline void CheckHelper(const char* file,
56                               int line,
57                               const char* source,
58                               bool condition) {
59  if (!condition)
60    V8_Fatal(file, line, "CHECK(%s) failed", source);
61}
62
63
64// The CHECK macro checks that the given condition is true; if not, it
65// prints a message to stderr and aborts.
66#define CHECK(condition) CheckHelper(__FILE__, __LINE__, #condition, condition)
67
68
69// Helper function used by the CHECK_EQ function when given int
70// arguments.  Should not be called directly.
71static inline void CheckEqualsHelper(const char* file, int line,
72                                     const char* expected_source, int expected,
73                                     const char* value_source, int value) {
74  if (expected != value) {
75    V8_Fatal(file, line,
76             "CHECK_EQ(%s, %s) failed\n#   Expected: %i\n#   Found: %i",
77             expected_source, value_source, expected, value);
78  }
79}
80
81
82// Helper function used by the CHECK_EQ function when given int64_t
83// arguments.  Should not be called directly.
84static inline void CheckEqualsHelper(const char* file, int line,
85                                     const char* expected_source,
86                                     int64_t expected,
87                                     const char* value_source,
88                                     int64_t value) {
89  if (expected != value) {
90    // Print int64_t values in hex, as two int32s,
91    // to avoid platform-dependencies.
92    V8_Fatal(file, line,
93             "CHECK_EQ(%s, %s) failed\n#"
94             "   Expected: 0x%08x%08x\n#   Found: 0x%08x%08x",
95             expected_source, value_source,
96             static_cast<uint32_t>(expected >> 32),
97             static_cast<uint32_t>(expected),
98             static_cast<uint32_t>(value >> 32),
99             static_cast<uint32_t>(value));
100  }
101}
102
103
104// Helper function used by the CHECK_NE function when given int
105// arguments.  Should not be called directly.
106static inline void CheckNonEqualsHelper(const char* file,
107                                        int line,
108                                        const char* unexpected_source,
109                                        int unexpected,
110                                        const char* value_source,
111                                        int value) {
112  if (unexpected == value) {
113    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %i",
114             unexpected_source, value_source, value);
115  }
116}
117
118
119// Helper function used by the CHECK function when given string
120// arguments.  Should not be called directly.
121static inline void CheckEqualsHelper(const char* file,
122                                     int line,
123                                     const char* expected_source,
124                                     const char* expected,
125                                     const char* value_source,
126                                     const char* value) {
127  if ((expected == NULL && value != NULL) ||
128      (expected != NULL && value == NULL) ||
129      (expected != NULL && value != NULL && strcmp(expected, value) != 0)) {
130    V8_Fatal(file, line,
131             "CHECK_EQ(%s, %s) failed\n#   Expected: %s\n#   Found: %s",
132             expected_source, value_source, expected, value);
133  }
134}
135
136
137static inline void CheckNonEqualsHelper(const char* file,
138                                        int line,
139                                        const char* expected_source,
140                                        const char* expected,
141                                        const char* value_source,
142                                        const char* value) {
143  if (expected == value ||
144      (expected != NULL && value != NULL && strcmp(expected, value) == 0)) {
145    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %s",
146             expected_source, value_source, value);
147  }
148}
149
150
151// Helper function used by the CHECK function when given pointer
152// arguments.  Should not be called directly.
153static inline void CheckEqualsHelper(const char* file,
154                                     int line,
155                                     const char* expected_source,
156                                     const void* expected,
157                                     const char* value_source,
158                                     const void* value) {
159  if (expected != value) {
160    V8_Fatal(file, line,
161             "CHECK_EQ(%s, %s) failed\n#   Expected: %p\n#   Found: %p",
162             expected_source, value_source,
163             expected, value);
164  }
165}
166
167
168static inline void CheckNonEqualsHelper(const char* file,
169                                        int line,
170                                        const char* expected_source,
171                                        const void* expected,
172                                        const char* value_source,
173                                        const void* value) {
174  if (expected == value) {
175    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %p",
176             expected_source, value_source, value);
177  }
178}
179
180
181// Helper function used by the CHECK function when given floating
182// point arguments.  Should not be called directly.
183static inline void CheckEqualsHelper(const char* file,
184                                     int line,
185                                     const char* expected_source,
186                                     double expected,
187                                     const char* value_source,
188                                     double value) {
189  // Force values to 64 bit memory to truncate 80 bit precision on IA32.
190  volatile double* exp = new double[1];
191  *exp = expected;
192  volatile double* val = new double[1];
193  *val = value;
194  if (*exp != *val) {
195    V8_Fatal(file, line,
196             "CHECK_EQ(%s, %s) failed\n#   Expected: %f\n#   Found: %f",
197             expected_source, value_source, *exp, *val);
198  }
199  delete[] exp;
200  delete[] val;
201}
202
203
204static inline void CheckNonEqualsHelper(const char* file,
205                                     int line,
206                                     const char* expected_source,
207                                     double expected,
208                                     const char* value_source,
209                                     double value) {
210  // Force values to 64 bit memory to truncate 80 bit precision on IA32.
211  volatile double* exp = new double[1];
212  *exp = expected;
213  volatile double* val = new double[1];
214  *val = value;
215  if (*exp == *val) {
216    V8_Fatal(file, line,
217             "CHECK_NE(%s, %s) failed\n#   Value: %f",
218             expected_source, value_source, *val);
219  }
220  delete[] exp;
221  delete[] val;
222}
223
224
225#define CHECK_EQ(expected, value) CheckEqualsHelper(__FILE__, __LINE__, \
226  #expected, expected, #value, value)
227
228
229#define CHECK_NE(unexpected, value) CheckNonEqualsHelper(__FILE__, __LINE__, \
230  #unexpected, unexpected, #value, value)
231
232
233#define CHECK_GT(a, b) CHECK((a) > (b))
234#define CHECK_GE(a, b) CHECK((a) >= (b))
235#define CHECK_LT(a, b) CHECK((a) < (b))
236#define CHECK_LE(a, b) CHECK((a) <= (b))
237
238
239// This is inspired by the static assertion facility in boost.  This
240// is pretty magical.  If it causes you trouble on a platform you may
241// find a fix in the boost code.
242template <bool> class StaticAssertion;
243template <> class StaticAssertion<true> { };
244// This macro joins two tokens.  If one of the tokens is a macro the
245// helper call causes it to be resolved before joining.
246#define SEMI_STATIC_JOIN(a, b) SEMI_STATIC_JOIN_HELPER(a, b)
247#define SEMI_STATIC_JOIN_HELPER(a, b) a##b
248// Causes an error during compilation of the condition is not
249// statically known to be true.  It is formulated as a typedef so that
250// it can be used wherever a typedef can be used.  Beware that this
251// actually causes each use to introduce a new defined type with a
252// name depending on the source line.
253template <int> class StaticAssertionHelper { };
254#define STATIC_CHECK(test)                                                  \
255  typedef                                                                   \
256    StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>(test)>)> \
257    SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
258
259
260namespace v8 { namespace internal {
261
262bool EnableSlowAsserts();
263
264} }  // namespace v8::internal
265
266// The ASSERT macro is equivalent to CHECK except that it only
267// generates code in debug builds.
268#ifdef DEBUG
269#define ASSERT_RESULT(expr)  CHECK(expr)
270#define ASSERT(condition)    CHECK(condition)
271#define ASSERT_EQ(v1, v2)    CHECK_EQ(v1, v2)
272#define ASSERT_NE(v1, v2)    CHECK_NE(v1, v2)
273#define ASSERT_GE(v1, v2)    CHECK_GE(v1, v2)
274#define ASSERT_LT(v1, v2)    CHECK_LT(v1, v2)
275#define ASSERT_LE(v1, v2)    CHECK_LE(v1, v2)
276#define SLOW_ASSERT(condition) if (EnableSlowAsserts()) CHECK(condition)
277#else
278#define ASSERT_RESULT(expr)     (expr)
279#define ASSERT(condition)      ((void) 0)
280#define ASSERT_EQ(v1, v2)      ((void) 0)
281#define ASSERT_NE(v1, v2)      ((void) 0)
282#define ASSERT_GE(v1, v2)      ((void) 0)
283#define ASSERT_LT(v1, v2)      ((void) 0)
284#define ASSERT_LE(v1, v2)      ((void) 0)
285#define SLOW_ASSERT(condition) ((void) 0)
286#endif
287// Static asserts has no impact on runtime performance, so they can be
288// safely enabled in release mode. Moreover, the ((void) 0) expression
289// obeys different syntax rules than typedef's, e.g. it can't appear
290// inside class declaration, this leads to inconsistency between debug
291// and release compilation modes behavior.
292#define STATIC_ASSERT(test)  STATIC_CHECK(test)
293
294#define ASSERT_NOT_NULL(p)  ASSERT_NE(NULL, p)
295
296#endif  // V8_CHECKS_H_
297