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"
34 extern "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.
CheckEqualsHelper(const char * file,int line,const char * expected_source,int expected,const char * value_source,int value)65 inline 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.
CheckEqualsHelper(const char * file,int line,const char * expected_source,int64_t expected,const char * value_source,int64_t value)78 inline 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.
CheckNonEqualsHelper(const char * file,int line,const char * unexpected_source,int unexpected,const char * value_source,int value)100 inline 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.
CheckEqualsHelper(const char * file,int line,const char * expected_source,const char * expected,const char * value_source,const char * value)115 inline 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
CheckNonEqualsHelper(const char * file,int line,const char * expected_source,const char * expected,const char * value_source,const char * value)131 inline 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.
CheckEqualsHelper(const char * file,int line,const char * expected_source,const void * expected,const char * value_source,const void * value)147 inline 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
CheckNonEqualsHelper(const char * file,int line,const char * expected_source,const void * expected,const char * value_source,const void * value)162 inline 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.
CheckEqualsHelper(const char * file,int line,const char * expected_source,double expected,const char * value_source,double value)177 inline 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
CheckNonEqualsHelper(const char * file,int line,const char * expected_source,double expected,const char * value_source,double value)198 inline 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 // This is inspired by the static assertion facility in boost. This
234 // is pretty magical. If it causes you trouble on a platform you may
235 // find a fix in the boost code.
236 template <bool> class StaticAssertion;
237 template <> class StaticAssertion<true> { };
238 // This macro joins two tokens. If one of the tokens is a macro the
239 // helper call causes it to be resolved before joining.
240 #define SEMI_STATIC_JOIN(a, b) SEMI_STATIC_JOIN_HELPER(a, b)
241 #define SEMI_STATIC_JOIN_HELPER(a, b) a##b
242 // Causes an error during compilation of the condition is not
243 // statically known to be true. It is formulated as a typedef so that
244 // it can be used wherever a typedef can be used. Beware that this
245 // actually causes each use to introduce a new defined type with a
246 // name depending on the source line.
247 template <int> class StaticAssertionHelper { };
248 #define STATIC_CHECK(test) \
249 typedef \
250 StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>((test))>)> \
251 SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
252
253
254 extern bool FLAG_enable_slow_asserts;
255
256
257 // The ASSERT macro is equivalent to CHECK except that it only
258 // generates code in debug builds.
259 #ifdef DEBUG
260 #define ASSERT_RESULT(expr) CHECK(expr)
261 #define ASSERT(condition) CHECK(condition)
262 #define ASSERT_EQ(v1, v2) CHECK_EQ(v1, v2)
263 #define ASSERT_NE(v1, v2) CHECK_NE(v1, v2)
264 #define ASSERT_GE(v1, v2) CHECK_GE(v1, v2)
265 #define ASSERT_LT(v1, v2) CHECK_LT(v1, v2)
266 #define ASSERT_LE(v1, v2) CHECK_LE(v1, v2)
267 #define SLOW_ASSERT(condition) CHECK(!FLAG_enable_slow_asserts || (condition))
268 #else
269 #define ASSERT_RESULT(expr) (expr)
270 #define ASSERT(condition) ((void) 0)
271 #define ASSERT_EQ(v1, v2) ((void) 0)
272 #define ASSERT_NE(v1, v2) ((void) 0)
273 #define ASSERT_GE(v1, v2) ((void) 0)
274 #define ASSERT_LT(v1, v2) ((void) 0)
275 #define ASSERT_LE(v1, v2) ((void) 0)
276 #define SLOW_ASSERT(condition) ((void) 0)
277 #endif
278 // Static asserts has no impact on runtime performance, so they can be
279 // safely enabled in release mode. Moreover, the ((void) 0) expression
280 // obeys different syntax rules than typedef's, e.g. it can't appear
281 // inside class declaration, this leads to inconsistency between debug
282 // and release compilation modes behavior.
283 #define STATIC_ASSERT(test) STATIC_CHECK(test)
284
285 #define ASSERT_NOT_NULL(p) ASSERT_NE(NULL, p)
286
287 #endif // V8_CHECKS_H_
288