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