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. 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. 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. 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. 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 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. 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 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. 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 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