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