1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mfbt/Assertions.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,428 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* Implementations of runtime and static assertion macros for C and C++. */ 1.11 + 1.12 +#ifndef mozilla_Assertions_h 1.13 +#define mozilla_Assertions_h 1.14 + 1.15 +#include "mozilla/Attributes.h" 1.16 +#include "mozilla/Compiler.h" 1.17 +#include "mozilla/Likely.h" 1.18 +#include "mozilla/MacroArgs.h" 1.19 + 1.20 +#include <stddef.h> 1.21 +#include <stdio.h> 1.22 +#include <stdlib.h> 1.23 +#ifdef WIN32 1.24 + /* 1.25 + * TerminateProcess and GetCurrentProcess are defined in <winbase.h>, which 1.26 + * further depends on <windef.h>. We hardcode these few definitions manually 1.27 + * because those headers clutter the global namespace with a significant 1.28 + * number of undesired macros and symbols. 1.29 + */ 1.30 +# ifdef __cplusplus 1.31 + extern "C" { 1.32 +# endif 1.33 + __declspec(dllimport) int __stdcall 1.34 + TerminateProcess(void* hProcess, unsigned int uExitCode); 1.35 + __declspec(dllimport) void* __stdcall GetCurrentProcess(void); 1.36 +# ifdef __cplusplus 1.37 + } 1.38 +# endif 1.39 +#else 1.40 +# include <signal.h> 1.41 +#endif 1.42 +#ifdef ANDROID 1.43 +# include <android/log.h> 1.44 +#endif 1.45 + 1.46 +/* 1.47 + * MOZ_STATIC_ASSERT may be used to assert a condition *at compile time* in C. 1.48 + * In C++11, static_assert is provided by the compiler to the same effect. 1.49 + * This can be useful when you make certain assumptions about what must hold for 1.50 + * optimal, or even correct, behavior. For example, you might assert that the 1.51 + * size of a struct is a multiple of the target architecture's word size: 1.52 + * 1.53 + * struct S { ... }; 1.54 + * // C 1.55 + * MOZ_STATIC_ASSERT(sizeof(S) % sizeof(size_t) == 0, 1.56 + * "S should be a multiple of word size for efficiency"); 1.57 + * // C++11 1.58 + * static_assert(sizeof(S) % sizeof(size_t) == 0, 1.59 + * "S should be a multiple of word size for efficiency"); 1.60 + * 1.61 + * This macro can be used in any location where both an extern declaration and a 1.62 + * typedef could be used. 1.63 + */ 1.64 +#ifndef __cplusplus 1.65 + /* 1.66 + * Some of the definitions below create an otherwise-unused typedef. This 1.67 + * triggers compiler warnings with some versions of gcc, so mark the typedefs 1.68 + * as permissibly-unused to disable the warnings. 1.69 + */ 1.70 +# if defined(__GNUC__) 1.71 +# define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) 1.72 +# else 1.73 +# define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE /* nothing */ 1.74 +# endif 1.75 +# define MOZ_STATIC_ASSERT_GLUE1(x, y) x##y 1.76 +# define MOZ_STATIC_ASSERT_GLUE(x, y) MOZ_STATIC_ASSERT_GLUE1(x, y) 1.77 +# if defined(__SUNPRO_CC) 1.78 + /* 1.79 + * The Sun Studio C++ compiler is buggy when declaring, inside a function, 1.80 + * another extern'd function with an array argument whose length contains a 1.81 + * sizeof, triggering the error message "sizeof expression not accepted as 1.82 + * size of array parameter". This bug (6688515, not public yet) would hit 1.83 + * defining moz_static_assert as a function, so we always define an extern 1.84 + * array for Sun Studio. 1.85 + * 1.86 + * We include the line number in the symbol name in a best-effort attempt 1.87 + * to avoid conflicts (see below). 1.88 + */ 1.89 +# define MOZ_STATIC_ASSERT(cond, reason) \ 1.90 + extern char MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)[(cond) ? 1 : -1] 1.91 +# elif defined(__COUNTER__) 1.92 + /* 1.93 + * If there was no preferred alternative, use a compiler-agnostic version. 1.94 + * 1.95 + * Note that the non-__COUNTER__ version has a bug in C++: it can't be used 1.96 + * in both |extern "C"| and normal C++ in the same translation unit. (Alas 1.97 + * |extern "C"| isn't allowed in a function.) The only affected compiler 1.98 + * we really care about is gcc 4.2. For that compiler and others like it, 1.99 + * we include the line number in the function name to do the best we can to 1.100 + * avoid conflicts. These should be rare: a conflict would require use of 1.101 + * MOZ_STATIC_ASSERT on the same line in separate files in the same 1.102 + * translation unit, *and* the uses would have to be in code with 1.103 + * different linkage, *and* the first observed use must be in C++-linkage 1.104 + * code. 1.105 + */ 1.106 +# define MOZ_STATIC_ASSERT(cond, reason) \ 1.107 + typedef int MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __COUNTER__)[(cond) ? 1 : -1] MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE 1.108 +# else 1.109 +# define MOZ_STATIC_ASSERT(cond, reason) \ 1.110 + extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1]) MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE 1.111 +# endif 1.112 + 1.113 +#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) MOZ_STATIC_ASSERT(!(cond) || (expr), reason) 1.114 +#else 1.115 +#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) static_assert(!(cond) || (expr), reason) 1.116 +#endif 1.117 + 1.118 +#ifdef __cplusplus 1.119 +extern "C" { 1.120 +#endif 1.121 + 1.122 +/* 1.123 + * Prints |s| as an assertion failure (using file and ln as the location of the 1.124 + * assertion) to the standard debug-output channel. 1.125 + * 1.126 + * Usually you should use MOZ_ASSERT or MOZ_CRASH instead of this method. This 1.127 + * method is primarily for internal use in this header, and only secondarily 1.128 + * for use in implementing release-build assertions. 1.129 + */ 1.130 +static MOZ_ALWAYS_INLINE void 1.131 +MOZ_ReportAssertionFailure(const char* s, const char* file, int ln) 1.132 +{ 1.133 +#ifdef ANDROID 1.134 + __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert", 1.135 + "Assertion failure: %s, at %s:%d\n", s, file, ln); 1.136 +#else 1.137 + fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln); 1.138 + fflush(stderr); 1.139 +#endif 1.140 +} 1.141 + 1.142 +static MOZ_ALWAYS_INLINE void 1.143 +MOZ_ReportCrash(const char* s, const char* file, int ln) 1.144 +{ 1.145 +#ifdef ANDROID 1.146 + __android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH", 1.147 + "Hit MOZ_CRASH(%s) at %s:%d\n", s, file, ln); 1.148 +#else 1.149 + fprintf(stderr, "Hit MOZ_CRASH(%s) at %s:%d\n", s, file, ln); 1.150 + fflush(stderr); 1.151 +#endif 1.152 +} 1.153 + 1.154 +/** 1.155 + * MOZ_REALLY_CRASH is used in the implementation of MOZ_CRASH(). You should 1.156 + * call MOZ_CRASH instead. 1.157 + */ 1.158 +#if defined(_MSC_VER) 1.159 + /* 1.160 + * On MSVC use the __debugbreak compiler intrinsic, which produces an inline 1.161 + * (not nested in a system function) breakpoint. This distinctively invokes 1.162 + * Breakpad without requiring system library symbols on all stack-processing 1.163 + * machines, as a nested breakpoint would require. 1.164 + * 1.165 + * We use TerminateProcess with the exit code aborting would generate 1.166 + * because we don't want to invoke atexit handlers, destructors, library 1.167 + * unload handlers, and so on when our process might be in a compromised 1.168 + * state. 1.169 + * 1.170 + * We don't use abort() because it'd cause Windows to annoyingly pop up the 1.171 + * process error dialog multiple times. See bug 345118 and bug 426163. 1.172 + * 1.173 + * We follow TerminateProcess() with a call to MOZ_NoReturn() so that the 1.174 + * compiler doesn't hassle us to provide a return statement after a 1.175 + * MOZ_REALLY_CRASH() call. 1.176 + * 1.177 + * (Technically these are Windows requirements, not MSVC requirements. But 1.178 + * practically you need MSVC for debugging, and we only ship builds created 1.179 + * by MSVC, so doing it this way reduces complexity.) 1.180 + */ 1.181 + 1.182 +__declspec(noreturn) __inline void MOZ_NoReturn() {} 1.183 + 1.184 +# ifdef __cplusplus 1.185 +# define MOZ_REALLY_CRASH() \ 1.186 + do { \ 1.187 + ::__debugbreak(); \ 1.188 + *((volatile int*) NULL) = 123; \ 1.189 + ::TerminateProcess(::GetCurrentProcess(), 3); \ 1.190 + ::MOZ_NoReturn(); \ 1.191 + } while (0) 1.192 +# else 1.193 +# define MOZ_REALLY_CRASH() \ 1.194 + do { \ 1.195 + __debugbreak(); \ 1.196 + *((volatile int*) NULL) = 123; \ 1.197 + TerminateProcess(GetCurrentProcess(), 3); \ 1.198 + MOZ_NoReturn(); \ 1.199 + } while (0) 1.200 +# endif 1.201 +#else 1.202 +# ifdef __cplusplus 1.203 +# define MOZ_REALLY_CRASH() \ 1.204 + do { \ 1.205 + *((volatile int*) NULL) = 123; \ 1.206 + ::abort(); \ 1.207 + } while (0) 1.208 +# else 1.209 +# define MOZ_REALLY_CRASH() \ 1.210 + do { \ 1.211 + *((volatile int*) NULL) = 123; \ 1.212 + abort(); \ 1.213 + } while (0) 1.214 +# endif 1.215 +#endif 1.216 + 1.217 +/* 1.218 + * MOZ_CRASH([explanation-string]) crashes the program, plain and simple, in a 1.219 + * Breakpad-compatible way, in both debug and release builds. 1.220 + * 1.221 + * MOZ_CRASH is a good solution for "handling" failure cases when you're 1.222 + * unwilling or unable to handle them more cleanly -- for OOM, for likely memory 1.223 + * corruption, and so on. It's also a good solution if you need safe behavior 1.224 + * in release builds as well as debug builds. But if the failure is one that 1.225 + * should be debugged and fixed, MOZ_ASSERT is generally preferable. 1.226 + * 1.227 + * The optional explanation-string, if provided, must be a string literal 1.228 + * explaining why we're crashing. This argument is intended for use with 1.229 + * MOZ_CRASH() calls whose rationale is non-obvious; don't use it if it's 1.230 + * obvious why we're crashing. 1.231 + * 1.232 + * If we're a DEBUG build and we crash at a MOZ_CRASH which provides an 1.233 + * explanation-string, we print the string to stderr. Otherwise, we don't 1.234 + * print anything; this is because we want MOZ_CRASH to be 100% safe in release 1.235 + * builds, and it's hard to print to stderr safely when memory might have been 1.236 + * corrupted. 1.237 + */ 1.238 +#ifndef DEBUG 1.239 +# define MOZ_CRASH(...) MOZ_REALLY_CRASH() 1.240 +#else 1.241 +# define MOZ_CRASH(...) \ 1.242 + do { \ 1.243 + MOZ_ReportCrash("" __VA_ARGS__, __FILE__, __LINE__); \ 1.244 + MOZ_REALLY_CRASH(); \ 1.245 + } while(0) 1.246 +#endif 1.247 + 1.248 +#ifdef __cplusplus 1.249 +} /* extern "C" */ 1.250 +#endif 1.251 + 1.252 +/* 1.253 + * MOZ_ASSERT(expr [, explanation-string]) asserts that |expr| must be truthy in 1.254 + * debug builds. If it is, execution continues. Otherwise, an error message 1.255 + * including the expression and the explanation-string (if provided) is printed, 1.256 + * an attempt is made to invoke any existing debugger, and execution halts. 1.257 + * MOZ_ASSERT is fatal: no recovery is possible. Do not assert a condition 1.258 + * which can correctly be falsy. 1.259 + * 1.260 + * The optional explanation-string, if provided, must be a string literal 1.261 + * explaining the assertion. It is intended for use with assertions whose 1.262 + * correctness or rationale is non-obvious, and for assertions where the "real" 1.263 + * condition being tested is best described prosaically. Don't provide an 1.264 + * explanation if it's not actually helpful. 1.265 + * 1.266 + * // No explanation needed: pointer arguments often must not be NULL. 1.267 + * MOZ_ASSERT(arg); 1.268 + * 1.269 + * // An explanation can be helpful to explain exactly how we know an 1.270 + * // assertion is valid. 1.271 + * MOZ_ASSERT(state == WAITING_FOR_RESPONSE, 1.272 + * "given that <thingA> and <thingB>, we must have..."); 1.273 + * 1.274 + * // Or it might disambiguate multiple identical (save for their location) 1.275 + * // assertions of the same expression. 1.276 + * MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(), 1.277 + * "we already set [[PrimitiveThis]] for this Boolean object"); 1.278 + * MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(), 1.279 + * "we already set [[PrimitiveThis]] for this String object"); 1.280 + * 1.281 + * MOZ_ASSERT has no effect in non-debug builds. It is designed to catch bugs 1.282 + * *only* during debugging, not "in the field". If you want the latter, use 1.283 + * MOZ_RELEASE_ASSERT, which applies to non-debug builds as well. 1.284 + */ 1.285 + 1.286 +/* First the single-argument form. */ 1.287 +#define MOZ_ASSERT_HELPER1(expr) \ 1.288 + do { \ 1.289 + if (MOZ_UNLIKELY(!(expr))) { \ 1.290 + MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \ 1.291 + MOZ_REALLY_CRASH(); \ 1.292 + } \ 1.293 + } while (0) 1.294 +/* Now the two-argument form. */ 1.295 +#define MOZ_ASSERT_HELPER2(expr, explain) \ 1.296 + do { \ 1.297 + if (MOZ_UNLIKELY(!(expr))) { \ 1.298 + MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \ 1.299 + MOZ_REALLY_CRASH(); \ 1.300 + } \ 1.301 + } while (0) 1.302 + 1.303 +#define MOZ_RELEASE_ASSERT_GLUE(a, b) a b 1.304 +#define MOZ_RELEASE_ASSERT(...) \ 1.305 + MOZ_RELEASE_ASSERT_GLUE( \ 1.306 + MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_ASSERT_HELPER, __VA_ARGS__), \ 1.307 + (__VA_ARGS__)) 1.308 + 1.309 +#ifdef DEBUG 1.310 +# define MOZ_ASSERT(...) MOZ_RELEASE_ASSERT(__VA_ARGS__) 1.311 +#else 1.312 +# define MOZ_ASSERT(...) do { } while(0) 1.313 +#endif /* DEBUG */ 1.314 + 1.315 +/* 1.316 + * MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is 1.317 + * true. 1.318 + * 1.319 + * MOZ_ASSERT_IF(isPrime(num), num == 2 || isOdd(num)); 1.320 + * 1.321 + * As with MOZ_ASSERT, MOZ_ASSERT_IF has effect only in debug builds. It is 1.322 + * designed to catch bugs during debugging, not "in the field". 1.323 + */ 1.324 +#ifdef DEBUG 1.325 +# define MOZ_ASSERT_IF(cond, expr) \ 1.326 + do { \ 1.327 + if (cond) \ 1.328 + MOZ_ASSERT(expr); \ 1.329 + } while (0) 1.330 +#else 1.331 +# define MOZ_ASSERT_IF(cond, expr) do { } while (0) 1.332 +#endif 1.333 + 1.334 +/* 1.335 + * MOZ_ASSUME_UNREACHABLE_MARKER() expands to an expression which states that it is 1.336 + * undefined behavior for execution to reach this point. No guarantees are made 1.337 + * about what will happen if this is reached at runtime. Most code should 1.338 + * probably use the higher level MOZ_ASSUME_UNREACHABLE, which uses this when 1.339 + * appropriate. 1.340 + */ 1.341 +#if defined(__clang__) 1.342 +# define MOZ_ASSUME_UNREACHABLE_MARKER() __builtin_unreachable() 1.343 +#elif defined(__GNUC__) 1.344 + /* 1.345 + * __builtin_unreachable() was implemented in gcc 4.5. If we don't have 1.346 + * that, call a noreturn function; abort() will do nicely. Qualify the call 1.347 + * in C++ in case there's another abort() visible in local scope. 1.348 + */ 1.349 +# if MOZ_GCC_VERSION_AT_LEAST(4, 5, 0) 1.350 +# define MOZ_ASSUME_UNREACHABLE_MARKER() __builtin_unreachable() 1.351 +# else 1.352 +# ifdef __cplusplus 1.353 +# define MOZ_ASSUME_UNREACHABLE_MARKER() ::abort() 1.354 +# else 1.355 +# define MOZ_ASSUME_UNREACHABLE_MARKER() abort() 1.356 +# endif 1.357 +# endif 1.358 +#elif defined(_MSC_VER) 1.359 +# define MOZ_ASSUME_UNREACHABLE_MARKER() __assume(0) 1.360 +#else 1.361 +# ifdef __cplusplus 1.362 +# define MOZ_ASSUME_UNREACHABLE_MARKER() ::abort() 1.363 +# else 1.364 +# define MOZ_ASSUME_UNREACHABLE_MARKER() abort() 1.365 +# endif 1.366 +#endif 1.367 + 1.368 +/* 1.369 + * MOZ_ASSUME_UNREACHABLE([reason]) tells the compiler that it can assume that 1.370 + * the macro call cannot be reached during execution. This lets the compiler 1.371 + * generate better-optimized code under some circumstances, at the expense of 1.372 + * the program's behavior being undefined if control reaches the 1.373 + * MOZ_ASSUME_UNREACHABLE. 1.374 + * 1.375 + * In Gecko, you probably should not use this macro outside of performance- or 1.376 + * size-critical code, because it's unsafe. If you don't care about code size 1.377 + * or performance, you should probably use MOZ_ASSERT or MOZ_CRASH. 1.378 + * 1.379 + * SpiderMonkey is a different beast, and there it's acceptable to use 1.380 + * MOZ_ASSUME_UNREACHABLE more widely. 1.381 + * 1.382 + * Note that MOZ_ASSUME_UNREACHABLE is noreturn, so it's valid not to return a 1.383 + * value following a MOZ_ASSUME_UNREACHABLE call. 1.384 + * 1.385 + * Example usage: 1.386 + * 1.387 + * enum ValueType { 1.388 + * VALUE_STRING, 1.389 + * VALUE_INT, 1.390 + * VALUE_FLOAT 1.391 + * }; 1.392 + * 1.393 + * int ptrToInt(ValueType type, void* value) { 1.394 + * { 1.395 + * // We know for sure that type is either INT or FLOAT, and we want this 1.396 + * // code to run as quickly as possible. 1.397 + * switch (type) { 1.398 + * case VALUE_INT: 1.399 + * return *(int*) value; 1.400 + * case VALUE_FLOAT: 1.401 + * return (int) *(float*) value; 1.402 + * default: 1.403 + * MOZ_ASSUME_UNREACHABLE("can only handle VALUE_INT and VALUE_FLOAT"); 1.404 + * } 1.405 + * } 1.406 + */ 1.407 +#if defined(DEBUG) 1.408 +# define MOZ_ASSUME_UNREACHABLE(...) \ 1.409 + do { \ 1.410 + MOZ_ASSERT(false, "MOZ_ASSUME_UNREACHABLE(" __VA_ARGS__ ")"); \ 1.411 + MOZ_ASSUME_UNREACHABLE_MARKER(); \ 1.412 + } while (0) 1.413 +#else 1.414 +# define MOZ_ASSUME_UNREACHABLE(reason) MOZ_ASSUME_UNREACHABLE_MARKER() 1.415 +#endif 1.416 + 1.417 +/* 1.418 + * MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided 1.419 + * expression, in debug builds and in release builds both. Then, in debug 1.420 + * builds only, the value of the expression is asserted either true or false 1.421 + * using MOZ_ASSERT. 1.422 + */ 1.423 +#ifdef DEBUG 1.424 +# define MOZ_ALWAYS_TRUE(expr) MOZ_ASSERT((expr)) 1.425 +# define MOZ_ALWAYS_FALSE(expr) MOZ_ASSERT(!(expr)) 1.426 +#else 1.427 +# define MOZ_ALWAYS_TRUE(expr) ((void)(expr)) 1.428 +# define MOZ_ALWAYS_FALSE(expr) ((void)(expr)) 1.429 +#endif 1.430 + 1.431 +#endif /* mozilla_Assertions_h */