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