Bug 712129 - Add more assertion macro flavors to mfbt, and make the JS engine use mfbt's implementations where appropriate. r=cjones
authorJeff Walden <jwalden@mit.edu>
Mon, 19 Dec 2011 15:54:12 -0500
changeset 85681 0d7567cf0a67a44906ab85ba9f2acc6ead70ba63
parent 85680 cffea4a903accb901b02517270378f6d76403382
child 85682 8d4a9617fcd105c8e06d80abfd4b0c3de47ff486
push idunknown
push userunknown
push dateunknown
reviewerscjones
bugs712129
milestone12.0a1
Bug 712129 - Add more assertion macro flavors to mfbt, and make the JS engine use mfbt's implementations where appropriate. r=cjones
js/public/Utility.h
mfbt/Assertions.h
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -35,16 +35,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef js_utility_h__
 #define js_utility_h__
 
+#include "mozilla/Assertions.h"
+
 #include <stdlib.h>
 #include <string.h>
 
 #include "jstypes.h"
 
 #ifdef __cplusplus
 
 /* The public JS engine namespace. */
@@ -66,37 +68,29 @@ using namespace mozilla;
 JS_BEGIN_EXTERN_C
 
 /*
  * Pattern used to overwrite freed memory. If you are accessing an object with
  * this pattern, you probably have a dangling pointer.
  */
 #define JS_FREE_PATTERN 0xDA
 
-/* JS_ASSERT */
+#define JS_ASSERT(expr)           MOZ_ASSERT(expr)
+#define JS_ASSERT_IF(cond, expr)  MOZ_ASSERT_IF((cond), (expr))
+#define JS_NOT_REACHED(reason)    MOZ_NOT_REACHED(reason)
+#define JS_ALWAYS_TRUE(expr)      MOZ_ALWAYS_TRUE(expr)
+#define JS_ALWAYS_FALSE(expr)     MOZ_ALWAYS_FALSE(expr)
+
 #ifdef DEBUG
-# define JS_ASSERT(expr)                                                      \
-    ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
-# define JS_ASSERT_IF(cond, expr)                                             \
-    ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
-# define JS_NOT_REACHED(reason)                                               \
-    JS_Assert(reason, __FILE__, __LINE__)
-# define JS_ALWAYS_TRUE(expr) JS_ASSERT(expr)
-# define JS_ALWAYS_FALSE(expr) JS_ASSERT(!(expr))
 # ifdef JS_THREADSAFE
 #  define JS_THREADSAFE_ASSERT(expr) JS_ASSERT(expr)
 # else
 #  define JS_THREADSAFE_ASSERT(expr) ((void) 0)
 # endif
 #else
-# define JS_ASSERT(expr)         ((void) 0)
-# define JS_ASSERT_IF(cond,expr) ((void) 0)
-# define JS_NOT_REACHED(reason)
-# define JS_ALWAYS_TRUE(expr)    ((void) (expr))
-# define JS_ALWAYS_FALSE(expr)    ((void) (expr))
 # define JS_THREADSAFE_ASSERT(expr) ((void) 0)
 #endif
 
 /*
  * JS_STATIC_ASSERT
  *
  * A compile-time assert. "cond" must be a constant expression. The macro can
  * be used only in places where an "extern" declaration is allowed.
--- a/mfbt/Assertions.h
+++ b/mfbt/Assertions.h
@@ -65,19 +65,77 @@ extern MFBT_API(void)
 JS_Assert(const char* s, const char* file, int ln);
 
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
 /*
  * MOZ_ASSERT() is a "strong" assertion of state, like libc's
- * assert().  If a MOZ_ASSERT() fails in a debug build, the process in
- * which it fails will stop running in a loud and dramatic way.
+ * assert().
+ *
+ *   MOZ_ASSERT(twoToThePowerOf(5) == 32);
+ *
+ * If a MOZ_ASSERT() fails in a debug build, the process in which it fails will
+ * stop running in a loud and dramatic way.  It has no effect in an optimized
+ * build.  This macro is designed to catch bugs during debugging, not "in the
+ * field".
  */
 #ifdef DEBUG
 #  define MOZ_ASSERT(expr_)                                      \
      ((expr_) ? ((void)0) : JS_Assert(#expr_, __FILE__, __LINE__))
 #else
 #  define MOZ_ASSERT(expr_) ((void)0)
 #endif /* DEBUG */
 
+/*
+ * MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is
+ * true.
+ *
+ *   MOZ_ASSERT_IF(isPrime(num), num == 2 || isOdd(num));
+ *
+ * As with MOZ_ASSERT, MOZ_ASSERT_IF has effect only in debug builds.  It is
+ * designed to catch bugs during debugging, not "in the field".
+ */
+#ifdef DEBUG
+#  define MOZ_ASSERT_IF(cond, expr)  ((cond) ? MOZ_ASSERT(expr) : ((void)0))
+#else
+#  define MOZ_ASSERT_IF(cond, expr)  ((void)0)
+#endif
+
+/*
+ * MOZ_NOT_REACHED(reason) indicates that the given point can't be reached
+ * during execution: simply reaching that point in execution is a bug.  It takes
+ * as an argument an error message indicating the reason why that point should
+ * not have been reachable.
+ *
+ *   // ...in a language parser...
+ *   void handle(BooleanLiteralNode node)
+ *   {
+ *     if (node.isTrue())
+ *       handleTrueLiteral();
+ *     else if (node.isFalse())
+ *       handleFalseLiteral();
+ *     else
+ *       MOZ_NOT_REACHED("boolean literal that's not true or false?");
+ *   }
+ */
+#ifdef DEBUG
+#  define MOZ_NOT_REACHED(reason)    JS_Assert(reason, __FILE__, __LINE__)
+#else
+#  define MOZ_NOT_REACHED(reason)    ((void)0)
+#endif
+
+/*
+ * MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided
+ * expression, in debug builds and in release builds both.  Then, in debug
+ * builds only, the value of the expression is asserted either true or false
+ * using MOZ_ASSERT.
+ */
+#ifdef DEBUG
+#  define MOZ_ALWAYS_TRUE(expr)      MOZ_ASSERT((expr))
+#  define MOZ_ALWAYS_FALSE(expr)     MOZ_ASSERT(!(expr))
+#else
+#  define MOZ_ALWAYS_TRUE(expr)      ((void)(expr))
+#  define MOZ_ALWAYS_FALSE(expr)     ((void)(expr))
+#endif
+
 #endif /* mozilla_Assertions_h_ */