Home | History | Annotate | Download | only in src
      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