1// Copyright 2012 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// The CHECK macro checks that the given condition is true; if not, it
55// prints a message to stderr and aborts.
56#define CHECK(condition) do {                                       \
57    if (!(condition)) {                                             \
58      V8_Fatal(__FILE__, __LINE__, "CHECK(%s) failed", #condition); \
59    }                                                               \
60  } while (0)
61
62
63// Helper function used by the CHECK_EQ function when given int
64// arguments.  Should not be called directly.
65inline void CheckEqualsHelper(const char* file, int line,
66                              const char* expected_source, int expected,
67                              const char* value_source, int value) {
68  if (expected != value) {
69    V8_Fatal(file, line,
70             "CHECK_EQ(%s, %s) failed\n#   Expected: %i\n#   Found: %i",
71             expected_source, value_source, expected, value);
72  }
73}
74
75
76// Helper function used by the CHECK_EQ function when given int64_t
77// arguments.  Should not be called directly.
78inline void CheckEqualsHelper(const char* file, int line,
79                              const char* expected_source,
80                              int64_t expected,
81                              const char* value_source,
82                              int64_t value) {
83  if (expected != value) {
84    // Print int64_t values in hex, as two int32s,
85    // to avoid platform-dependencies.
86    V8_Fatal(file, line,
87             "CHECK_EQ(%s, %s) failed\n#"
88             "   Expected: 0x%08x%08x\n#   Found: 0x%08x%08x",
89             expected_source, value_source,
90             static_cast<uint32_t>(expected >> 32),
91             static_cast<uint32_t>(expected),
92             static_cast<uint32_t>(value >> 32),
93             static_cast<uint32_t>(value));
94  }
95}
96
97
98// Helper function used by the CHECK_NE function when given int
99// arguments.  Should not be called directly.
100inline void CheckNonEqualsHelper(const char* file,
101                                 int line,
102                                 const char* unexpected_source,
103                                 int unexpected,
104                                 const char* value_source,
105                                 int value) {
106  if (unexpected == value) {
107    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %i",
108             unexpected_source, value_source, value);
109  }
110}
111
112
113// Helper function used by the CHECK function when given string
114// arguments.  Should not be called directly.
115inline void CheckEqualsHelper(const char* file,
116                              int line,
117                              const char* expected_source,
118                              const char* expected,
119                              const char* value_source,
120                              const char* value) {
121  if ((expected == NULL && value != NULL) ||
122      (expected != NULL && value == NULL) ||
123      (expected != NULL && value != NULL && strcmp(expected, value) != 0)) {
124    V8_Fatal(file, line,
125             "CHECK_EQ(%s, %s) failed\n#   Expected: %s\n#   Found: %s",
126             expected_source, value_source, expected, value);
127  }
128}
129
130
131inline void CheckNonEqualsHelper(const char* file,
132                                 int line,
133                                 const char* expected_source,
134                                 const char* expected,
135                                 const char* value_source,
136                                 const char* value) {
137  if (expected == value ||
138      (expected != NULL && value != NULL && strcmp(expected, value) == 0)) {
139    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %s",
140             expected_source, value_source, value);
141  }
142}
143
144
145// Helper function used by the CHECK function when given pointer
146// arguments.  Should not be called directly.
147inline void CheckEqualsHelper(const char* file,
148                              int line,
149                              const char* expected_source,
150                              const void* expected,
151                              const char* value_source,
152                              const void* value) {
153  if (expected != value) {
154    V8_Fatal(file, line,
155             "CHECK_EQ(%s, %s) failed\n#   Expected: %p\n#   Found: %p",
156             expected_source, value_source,
157             expected, value);
158  }
159}
160
161
162inline void CheckNonEqualsHelper(const char* file,
163                                 int line,
164                                 const char* expected_source,
165                                 const void* expected,
166                                 const char* value_source,
167                                 const void* value) {
168  if (expected == value) {
169    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %p",
170             expected_source, value_source, value);
171  }
172}
173
174
175// Helper function used by the CHECK function when given floating
176// point arguments.  Should not be called directly.
177inline void CheckEqualsHelper(const char* file,
178                              int line,
179                              const char* expected_source,
180                              double expected,
181                              const char* value_source,
182                              double value) {
183  // Force values to 64 bit memory to truncate 80 bit precision on IA32.
184  volatile double* exp = new double[1];
185  *exp = expected;
186  volatile double* val = new double[1];
187  *val = value;
188  if (*exp != *val) {
189    V8_Fatal(file, line,
190             "CHECK_EQ(%s, %s) failed\n#   Expected: %f\n#   Found: %f",
191             expected_source, value_source, *exp, *val);
192  }
193  delete[] exp;
194  delete[] val;
195}
196
197
198inline void CheckNonEqualsHelper(const char* file,
199                                 int line,
200                                 const char* expected_source,
201                                 double expected,
202                                 const char* value_source,
203                                 double value) {
204  // Force values to 64 bit memory to truncate 80 bit precision on IA32.
205  volatile double* exp = new double[1];
206  *exp = expected;
207  volatile double* val = new double[1];
208  *val = value;
209  if (*exp == *val) {
210    V8_Fatal(file, line,
211             "CHECK_NE(%s, %s) failed\n#   Value: %f",
212             expected_source, value_source, *val);
213  }
214  delete[] exp;
215  delete[] val;
216}
217
218
219#define CHECK_EQ(expected, value) CheckEqualsHelper(__FILE__, __LINE__, \
220  #expected, expected, #value, value)
221
222
223#define CHECK_NE(unexpected, value) CheckNonEqualsHelper(__FILE__, __LINE__, \
224  #unexpected, unexpected, #value, value)
225
226
227#define CHECK_GT(a, b) CHECK((a) > (b))
228#define CHECK_GE(a, b) CHECK((a) >= (b))
229#define CHECK_LT(a, b) CHECK((a) < (b))
230#define CHECK_LE(a, b) CHECK((a) <= (b))
231
232
233// Use C++11 static_assert if possible, which gives error
234// messages that are easier to understand on first sight.
235#if __cplusplus >= 201103L
236#define STATIC_CHECK(test) static_assert(test, #test)
237#else
238// This is inspired by the static assertion facility in boost.  This
239// is pretty magical.  If it causes you trouble on a platform you may
240// find a fix in the boost code.
241template <bool> class StaticAssertion;
242template <> class StaticAssertion<true> { };
243// This macro joins two tokens.  If one of the tokens is a macro the
244// helper call causes it to be resolved before joining.
245#define SEMI_STATIC_JOIN(a, b) SEMI_STATIC_JOIN_HELPER(a, b)
246#define SEMI_STATIC_JOIN_HELPER(a, b) a##b
247// Causes an error during compilation of the condition is not
248// statically known to be true.  It is formulated as a typedef so that
249// it can be used wherever a typedef can be used.  Beware that this
250// actually causes each use to introduce a new defined type with a
251// name depending on the source line.
252template <int> class StaticAssertionHelper { };
253#define STATIC_CHECK(test)                                                    \
254  typedef                                                                     \
255    StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>((test))>)> \
256    SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
257#endif
258
259
260extern bool FLAG_enable_slow_asserts;
261
262
263// The ASSERT macro is equivalent to CHECK except that it only
264// generates code in debug builds.
265#ifdef DEBUG
266#define ASSERT_RESULT(expr)    CHECK(expr)
267#define ASSERT(condition)      CHECK(condition)
268#define ASSERT_EQ(v1, v2)      CHECK_EQ(v1, v2)
269#define ASSERT_NE(v1, v2)      CHECK_NE(v1, v2)
270#define ASSERT_GE(v1, v2)      CHECK_GE(v1, v2)
271#define ASSERT_LT(v1, v2)      CHECK_LT(v1, v2)
272#define ASSERT_LE(v1, v2)      CHECK_LE(v1, v2)
273#define SLOW_ASSERT(condition) CHECK(!FLAG_enable_slow_asserts || (condition))
274#else
275#define ASSERT_RESULT(expr)    (expr)
276#define ASSERT(condition)      ((void) 0)
277#define ASSERT_EQ(v1, v2)      ((void) 0)
278#define ASSERT_NE(v1, v2)      ((void) 0)
279#define ASSERT_GE(v1, v2)      ((void) 0)
280#define ASSERT_LT(v1, v2)      ((void) 0)
281#define ASSERT_LE(v1, v2)      ((void) 0)
282#define SLOW_ASSERT(condition) ((void) 0)
283#endif
284// Static asserts has no impact on runtime performance, so they can be
285// safely enabled in release mode. Moreover, the ((void) 0) expression
286// obeys different syntax rules than typedef's, e.g. it can't appear
287// inside class declaration, this leads to inconsistency between debug
288// and release compilation modes behavior.
289#define STATIC_ASSERT(test)  STATIC_CHECK(test)
290
291#define ASSERT_NOT_NULL(p)  ASSERT_NE(NULL, p)
292
293// "Extra checks" are lightweight checks that are enabled in some release
294// builds.
295#ifdef ENABLE_EXTRA_CHECKS
296#define EXTRA_CHECK(condition) CHECK(condition)
297#else
298#define EXTRA_CHECK(condition) ((void) 0)
299#endif
300
301#endif  // V8_CHECKS_H_
302