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