Bug 712939 - Replace a bunch more JS_STATIC_ASSERTs with static_assert. r=jandem
authorJeff Walden <jwalden@mit.edu>
Thu, 30 Oct 2014 14:28:27 -0700
changeset 240471 dcb90c3786e0b087314996263a96fbd23d810b42
parent 240470 5d6476e1fcfe12cd9447a494773252ba48c6d3b7
child 240472 37314ece19fa4c466c7146f9208a4aec4c013c75
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs712939
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 712939 - Replace a bunch more JS_STATIC_ASSERTs with static_assert. r=jandem
js/src/jit/BitSet.h
js/src/jsexn.cpp
js/src/jsexn.h
js/src/jsnum.cpp
js/src/json.cpp
js/src/jstypes.h
js/src/jsutil.cpp
js/src/vm/StructuredClone.cpp
--- a/js/src/jit/BitSet.h
+++ b/js/src/jit/BitSet.h
@@ -124,18 +124,17 @@ class BitSet::Iterator
         // Skip words containing only zeros.
         unsigned numWords = set_.numWords();
         const uint32_t *bits = set_.bits_;
         while (value_ == 0) {
             word_++;
             if (word_ == numWords)
                 return;
 
-            JS_STATIC_ASSERT(sizeof(value_) * 8 == BitSet::BitsPerWord);
-            index_ = word_ * sizeof(value_) * 8;
+            index_ = word_ * BitSet::BitsPerWord;
             value_ = bits[word_];
         }
 
         // Be careful: the result of CountTrailingZeroes32 is undefined if the
         // input is 0.
         int numZeros = mozilla::CountTrailingZeroes32(value_);
         index_ += numZeros;
         value_ >>= numZeros;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -485,26 +485,16 @@ exn_toSource(JSContext *cx, unsigned arg
     JSString *str = sb.finishString();
     if (!str)
         return false;
     args.rval().setString(str);
     return true;
 }
 #endif
 
-/* JSProto_ ordering for exceptions shall match JSEXN_ constants. */
-JS_STATIC_ASSERT(JSEXN_ERR == 0);
-JS_STATIC_ASSERT(JSProto_Error + JSEXN_INTERNALERR  == JSProto_InternalError);
-JS_STATIC_ASSERT(JSProto_Error + JSEXN_EVALERR      == JSProto_EvalError);
-JS_STATIC_ASSERT(JSProto_Error + JSEXN_RANGEERR     == JSProto_RangeError);
-JS_STATIC_ASSERT(JSProto_Error + JSEXN_REFERENCEERR == JSProto_ReferenceError);
-JS_STATIC_ASSERT(JSProto_Error + JSEXN_SYNTAXERR    == JSProto_SyntaxError);
-JS_STATIC_ASSERT(JSProto_Error + JSEXN_TYPEERR      == JSProto_TypeError);
-JS_STATIC_ASSERT(JSProto_Error + JSEXN_URIERR       == JSProto_URIError);
-
 /* static */ JSObject *
 ErrorObject::createProto(JSContext *cx, JSProtoKey key)
 {
     RootedObject errorProto(cx, GenericCreatePrototype(cx, key));
     if (!errorProto)
         return nullptr;
 
     Rooted<ErrorObject*> err(cx, &errorProto->as<ErrorObject>());
--- a/js/src/jsexn.h
+++ b/js/src/jsexn.h
@@ -81,16 +81,29 @@ js_ErrorFromException(JSContext *cx, js:
  *
  * errobj may be in a different compartment than cx, but it must be an Error
  * object (not a wrapper of one) and it must not be one of the standard error
  * prototype objects (errobj->getPrivate() must not be nullptr).
  */
 extern JSObject *
 js_CopyErrorObject(JSContext *cx, JS::Handle<js::ErrorObject*> errobj);
 
+static_assert(JSEXN_ERR == 0 &&
+              JSProto_Error + JSEXN_INTERNALERR == JSProto_InternalError &&
+              JSProto_Error + JSEXN_EVALERR == JSProto_EvalError &&
+              JSProto_Error + JSEXN_RANGEERR == JSProto_RangeError &&
+              JSProto_Error + JSEXN_REFERENCEERR == JSProto_ReferenceError &&
+              JSProto_Error + JSEXN_SYNTAXERR == JSProto_SyntaxError &&
+              JSProto_Error + JSEXN_TYPEERR == JSProto_TypeError &&
+              JSProto_Error + JSEXN_URIERR == JSProto_URIError &&
+              JSEXN_URIERR + 1 == JSEXN_LIMIT,
+              "GetExceptionProtoKey and ExnTypeFromProtoKey require that "
+              "each corresponding JSExnType and JSProtoKey value be separated "
+              "by the same constant value");
+
 static inline JSProtoKey
 GetExceptionProtoKey(JSExnType exn)
 {
     MOZ_ASSERT(JSEXN_ERR <= exn);
     MOZ_ASSERT(exn < JSEXN_LIMIT);
     return JSProtoKey(JSProto_Error + int(exn));
 }
 
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -537,19 +537,21 @@ num_toSource_impl(JSContext *cx, CallArg
 static bool
 num_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsNumber, num_toSource_impl>(cx, args);
 }
 #endif
 
-ToCStringBuf::ToCStringBuf() :dbuf(nullptr)
+ToCStringBuf::ToCStringBuf() : dbuf(nullptr)
 {
-    JS_STATIC_ASSERT(sbufSize >= DTOSTR_STANDARD_BUFFER_SIZE);
+    static_assert(sbufSize >= DTOSTR_STANDARD_BUFFER_SIZE,
+                  "builtin space must be large enough to store even the "
+                  "longest string produced by a conversion");
 }
 
 ToCStringBuf::~ToCStringBuf()
 {
     js_free(dbuf);
 }
 
 MOZ_ALWAYS_INLINE
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -42,23 +42,25 @@ const Class js::JSONClass = {
     JS_DeletePropertyStub,  /* delProperty */
     JS_PropertyStub,        /* getProperty */
     JS_StrictPropertyStub,  /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
-static inline bool IsQuoteSpecialCharacter(char16_t c)
+static inline bool
+IsQuoteSpecialCharacter(char16_t c)
 {
-    JS_STATIC_ASSERT('\b' < ' ');
-    JS_STATIC_ASSERT('\f' < ' ');
-    JS_STATIC_ASSERT('\n' < ' ');
-    JS_STATIC_ASSERT('\r' < ' ');
-    JS_STATIC_ASSERT('\t' < ' ');
+    static_assert('\b' < ' ', "'\\b' must be treated as special below");
+    static_assert('\f' < ' ', "'\\f' must be treated as special below");
+    static_assert('\n' < ' ', "'\\n' must be treated as special below");
+    static_assert('\r' < ' ', "'\\r' must be treated as special below");
+    static_assert('\t' < ' ', "'\\t' must be treated as special below");
+
     return c == '"' || c == '\\' || c < ' ';
 }
 
 /* ES5 15.12.3 Quote. */
 template <typename CharT>
 static bool
 Quote(StringBuffer &sb, JSLinearString *str)
 {
--- a/js/src/jstypes.h
+++ b/js/src/jstypes.h
@@ -17,16 +17,17 @@
 ** and take the following steps only in those C files, we take steps once here
 ** for all C files.
 **/
 
 #ifndef jstypes_h
 #define jstypes_h
 
 #include "mozilla/Attributes.h"
+#include "mozilla/Casting.h"
 #include "mozilla/Types.h"
 
 // jstypes.h is (or should be!) included by every file in SpiderMonkey.
 // js-config.h and jsversion.h also should be included by every file.
 // So include them here.
 // XXX: including them in js/RequiredDefines.h should be a better option, since
 // that is by definition the header file that should be included in all
 // SpiderMonkey code.  However, Gecko doesn't do this!  See bug 909576.
@@ -189,36 +190,30 @@
 #else
 # define JS_BITS_PER_WORD 32
 #endif
 
 /***********************************************************************
 ** MACROS:      JS_FUNC_TO_DATA_PTR
 **              JS_DATA_TO_FUNC_PTR
 ** DESCRIPTION:
-**      Macros to convert between function and data pointers assuming that
-**      they have the same size. Use them like this:
+**      Macros to convert between function and data pointers of the same
+**      size. Use them like this:
 **
 **      JSPropertyOp nativeGetter;
 **      JSObject *scriptedGetter;
 **      ...
 **      scriptedGetter = JS_FUNC_TO_DATA_PTR(JSObject *, nativeGetter);
 **      ...
 **      nativeGetter = JS_DATA_TO_FUNC_PTR(JSPropertyOp, scriptedGetter);
 **
 ***********************************************************************/
 
-#ifdef __GNUC__
-# define JS_FUNC_TO_DATA_PTR(type, fun) (__extension__ (type) (size_t) (fun))
-# define JS_DATA_TO_FUNC_PTR(type, ptr) (__extension__ (type) (size_t) (ptr))
-#else
-/* Use an extra (void *) cast for MSVC. */
-# define JS_FUNC_TO_DATA_PTR(type, fun) ((type) (void *) (fun))
-# define JS_DATA_TO_FUNC_PTR(type, ptr) ((type) (void *) (ptr))
-#endif
+#define JS_FUNC_TO_DATA_PTR(type, fun)  (mozilla::BitwiseCast<type>(fun))
+#define JS_DATA_TO_FUNC_PTR(type, ptr)  (mozilla::BitwiseCast<type>(ptr))
 
 #ifdef __GNUC__
 # define JS_EXTENSION __extension__
 # define JS_EXTENSION_(s) __extension__ ({ s; })
 #else
 # define JS_EXTENSION
 # define JS_EXTENSION_(s) s
 #endif
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -28,22 +28,16 @@ using mozilla::CeilingLog2Size;
 using mozilla::PodArrayZero;
 
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
 /* For JS_OOM_POSSIBLY_FAIL in jsutil.h. */
 JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations = UINT32_MAX;
 JS_PUBLIC_DATA(uint32_t) OOM_counter = 0;
 #endif
 
-/*
- * Checks the assumption that JS_FUNC_TO_DATA_PTR and JS_DATA_TO_FUNC_PTR
- * macros uses to implement casts between function and data pointers.
- */
-JS_STATIC_ASSERT(sizeof(void *) == sizeof(void (*)()));
-
 JS_PUBLIC_API(void)
 JS_Assert(const char *s, const char *file, int ln)
 {
     MOZ_ReportAssertionFailure(s, file, ln);
     MOZ_CRASH();
 }
 
 #ifdef __linux__
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -45,16 +45,17 @@
 #include "vm/TypedArrayObject.h"
 #include "vm/WrapperObject.h"
 
 #include "jscntxtinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 
+using mozilla::BitwiseCast;
 using mozilla::IsNaN;
 using mozilla::LittleEndian;
 using mozilla::NativeEndian;
 using JS::CanonicalizeNaN;
 
 // When you make updates here, make sure you consider whether you need to bump the
 // value of JS_STRUCTURED_CLONE_VERSION in js/public/StructuredClone.h.  You will
 // likely need to increment the version if anything at all changes in the serialization
@@ -199,17 +200,16 @@ class SCInput {
                               JSMSG_SC_BAD_SERIALIZED_DATA, "truncated");
          return false;
      }
 
   private:
     void staticAssertions() {
         JS_STATIC_ASSERT(sizeof(char16_t) == 2);
         JS_STATIC_ASSERT(sizeof(uint32_t) == 4);
-        JS_STATIC_ASSERT(sizeof(double) == 8);
     }
 
     JSContext *cx;
     uint64_t *point;
     uint64_t *bufEnd;
 };
 
 } /* namespace js */
@@ -629,48 +629,26 @@ SCOutput::writePair(uint32_t tag, uint32
      *
      * For example, JSVAL_TRUE is written using writePair(SCTAG_BOOLEAN, 1).
      * PairToUInt64 produces the number 0xFFFF000200000001.
      * That is written out as the bytes 01 00 00 00 02 00 FF FF.
      */
     return write(PairToUInt64(tag, data));
 }
 
-static inline uint64_t
-ReinterpretDoubleAsUInt64(double d)
-{
-    union {
-        double d;
-        uint64_t u;
-    } pun;
-    pun.d = d;
-    return pun.u;
-}
-
-static inline double
-ReinterpretUInt64AsDouble(uint64_t u)
-{
-    union {
-        uint64_t u;
-        double d;
-    } pun;
-    pun.u = u;
-    return pun.d;
-}
-
 static inline double
 ReinterpretPairAsDouble(uint32_t tag, uint32_t data)
 {
-    return ReinterpretUInt64AsDouble(PairToUInt64(tag, data));
+    return BitwiseCast<double>(PairToUInt64(tag, data));
 }
 
 bool
 SCOutput::writeDouble(double d)
 {
-    return write(ReinterpretDoubleAsUInt64(CanonicalizeNaN(d)));
+    return write(BitwiseCast<uint64_t>(CanonicalizeNaN(d)));
 }
 
 template <typename T>
 static void
 copyAndSwapToLittleEndian(void *dest, const T *src, size_t nelems)
 {
     if (nelems > 0)
         NativeEndian::copyAndSwapToLittleEndian(dest, src, nelems);
@@ -713,17 +691,19 @@ bool
 SCOutput::writeBytes(const void *p, size_t nbytes)
 {
     return writeArray((const uint8_t *) p, nbytes);
 }
 
 bool
 SCOutput::writeChars(const char16_t *p, size_t nchars)
 {
-    MOZ_ASSERT(sizeof(char16_t) == sizeof(uint16_t));
+    static_assert(sizeof(char16_t) == sizeof(uint16_t),
+                  "required so that treating char16_t[] memory as uint16_t[] "
+                  "memory is permissible");
     return writeArray((const uint16_t *) p, nchars);
 }
 
 bool
 SCOutput::writeChars(const Latin1Char *p, size_t nchars)
 {
     static_assert(sizeof(Latin1Char) == sizeof(uint8_t), "Latin1Char must fit in 1 byte");
     return writeBytes(p, nchars);