Bug 1264403 - Check for DEBUG mismatch between compiled code and library at runtime, r=Waldo
authorSteve Fink <sfink@mozilla.com>
Wed, 20 Jul 2016 18:25:02 -0700
changeset 346018 f4ffff32d7f46eb78bdaac0c2fd871f2dc1a26ad
parent 346017 f689b7b832afd0b8e98f6bf0ce265ea4415db9dd
child 346019 57356e7b5e91412e0e616d47de8649c348214791
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1264403
milestone50.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 1264403 - Check for DEBUG mismatch between compiled code and library at runtime, r=Waldo MozReview-Commit-ID: G40Dad5k8vb
js/public/Initialization.h
js/src/vm/DateTime.h
js/src/vm/Initialization.cpp
--- a/js/public/Initialization.h
+++ b/js/public/Initialization.h
@@ -20,16 +20,19 @@ enum class InitState { Uninitialized = 0
  * that should happen only once across all runtimes.  It's an API requirement
  * that JS_Init (and JS_ShutDown, if called) be called in a thread-aware
  * manner, so this (internal -- embedders, don't use!) variable doesn't need to
  * be atomic.
  */
 extern JS_PUBLIC_DATA(InitState)
 libraryInitState;
 
+extern JS_PUBLIC_API(const char*)
+InitWithFailureDiagnostic(bool isDebugBuild);
+
 } // namespace detail
 } // namespace JS
 
 // These are equivalent to ICU's |UMemAllocFn|, |UMemReallocFn|, and
 // |UMemFreeFn| types.  The first argument (called |context| in the ICU docs)
 // will always be nullptr and should be ignored.
 typedef void* (*JS_ICUAllocFn)(const void*, size_t size);
 typedef void* (*JS_ICUReallocFn)(const void*, void* p, size_t size);
@@ -53,26 +56,40 @@ JS_SetICUMemoryFunctions(JS_ICUAllocFn a
  * This method must be called before any other JSAPI method is used on any
  * thread.  Once it has been used, it is safe to call any JSAPI method, and it
  * remains safe to do so until JS_ShutDown is correctly called.
  *
  * It is currently not possible to initialize SpiderMonkey multiple times (that
  * is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
  * again).  This restriction may eventually be lifted.
  */
-extern JS_PUBLIC_API(bool)
-JS_Init(void);
+inline bool
+JS_Init(void)
+{
+#ifdef DEBUG
+    return !JS::detail::InitWithFailureDiagnostic(true);
+#else
+    return !JS::detail::InitWithFailureDiagnostic(false);
+#endif
+}
 
 /**
  * A variant of JS_Init. On success it returns nullptr. On failure it returns a
  * pointer to a string literal that describes how initialization failed, which
  * can be useful for debugging purposes.
  */
-extern JS_PUBLIC_API(const char*)
-JS_InitWithFailureDiagnostic(void);
+inline const char*
+JS_InitWithFailureDiagnostic(void)
+{
+#ifdef DEBUG
+    return JS::detail::InitWithFailureDiagnostic(true);
+#else
+    return JS::detail::InitWithFailureDiagnostic(false);
+#endif
+}
 
 /**
  * Destroy free-standing resources allocated by SpiderMonkey, not associated
  * with any runtime, context, or other structure.
  *
  * This method should be called after all other JSAPI data has been properly
  * cleaned up: every new runtime must have been destroyed, every new context
  * must have been destroyed, and so on.  Calling this method before all other
--- a/js/src/vm/DateTime.h
+++ b/js/src/vm/DateTime.h
@@ -114,17 +114,17 @@ class DateTimeInfo
                 continue;
         }
         ~AcquireLock() {
             MOZ_ASSERT(spinLock, "spinlock should have been acquired");
             spinLock = false;
         }
     };
 
-    friend const char* ::JS_InitWithFailureDiagnostic();
+    friend const char* JS::detail::InitWithFailureDiagnostic(bool);
 
     // Initialize global date/time tracking state.  This operation occurs
     // during, and is restricted to, SpiderMonkey initialization.
     static void init();
 
   public:
     /*
      * Get the DST offset in milliseconds at a UTC time.  This is usually
--- a/js/src/vm/Initialization.cpp
+++ b/js/src/vm/Initialization.cpp
@@ -54,74 +54,70 @@ CheckMessageParameterCounts()
     // parameters.
 # define MSG_DEF(name, count, exception, format)           \
         MOZ_ASSERT(MessageParameterCount(format) == count);
 # include "js.msg"
 # undef MSG_DEF
 }
 #endif /* DEBUG */
 
+#define RETURN_IF_FAIL(code) do { if (!code) return #code " failed"; } while (0)
+
 JS_PUBLIC_API(const char*)
-JS_InitWithFailureDiagnostic(void)
+JS::detail::InitWithFailureDiagnostic(bool isDebugBuild)
 {
+    // Verify that our DEBUG setting matches the caller's.
+#ifdef DEBUG
+    MOZ_RELEASE_ASSERT(isDebugBuild);
+#else
+    MOZ_RELEASE_ASSERT(!isDebugBuild);
+#endif
+
     MOZ_ASSERT(libraryInitState == InitState::Uninitialized,
                "must call JS_Init once before any JSAPI operation except "
                "JS_SetICUMemoryFunctions");
     MOZ_ASSERT(!JSRuntime::hasLiveRuntimes(),
                "how do we have live runtimes before JS_Init?");
 
     PRMJ_NowInit();
 
 #ifdef DEBUG
     CheckMessageParameterCounts();
 #endif
 
     using js::TlsPerThreadData;
-    if (!TlsPerThreadData.init())
-        return "JS_InitWithFailureDiagnostic: TlsPerThreadData.init() failed";
+    RETURN_IF_FAIL(TlsPerThreadData.init());
 
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
-    if (!js::oom::InitThreadType())
-        return "JS_InitWithFailureDiagnostic: js::oom::InitThreadType() failed";
+    RETURN_IF_FAIL(js::oom::InitThreadType());
     js::oom::SetThreadType(js::oom::THREAD_TYPE_MAIN);
 #endif
 
     js::jit::ExecutableAllocator::initStatic();
 
-    if (!js::jit::InitializeIon())
-        return "JS_InitWithFailureDiagnostic: js::jit::InitializeIon() failed";
+    RETURN_IF_FAIL(js::jit::InitializeIon());
 
     js::DateTimeInfo::init();
 
 #if EXPOSE_INTL_API
     UErrorCode err = U_ZERO_ERROR;
     u_init(&err);
     if (U_FAILURE(err))
-        return "JS_InitWithFailureDiagnostic: u_init() failed";
+        return "u_init() failed";
 #endif // EXPOSE_INTL_API
 
-    if (!js::CreateHelperThreadsState())
-        return "JS_InitWithFailureDiagnostic: js::CreateHelperThreadState() failed";
-
-    if (!FutexRuntime::initialize())
-        return "JS_InitWithFailureDiagnostic: FutexRuntime::initialize() failed";
-
-    if (!js::gcstats::Statistics::initialize())
-        return "JS_InitWithFailureDiagnostic: js::gcstats::Statistics::initialize() failed";
+    RETURN_IF_FAIL(js::CreateHelperThreadsState());
+    RETURN_IF_FAIL(FutexRuntime::initialize());
+    RETURN_IF_FAIL(js::gcstats::Statistics::initialize());
 
     libraryInitState = InitState::Running;
     return nullptr;
 }
 
-JS_PUBLIC_API(bool)
-JS_Init(void)
-{
-    const char* failure = JS_InitWithFailureDiagnostic();
-    return !failure;
-}
+#undef RETURN_IF_FAIL
 
 JS_PUBLIC_API(void)
 JS_ShutDown(void)
 {
     MOZ_ASSERT(libraryInitState == InitState::Running,
                "JS_ShutDown must only be called after JS_Init and can't race with it");
 #ifdef DEBUG
     if (JSRuntime::hasLiveRuntimes()) {