• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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