Bug 717540 - Remove MFBT dependency on JS_Assert, add MOZ_Assert, and use it for WTF assertions. r=waldo,r=khuey
authorMike Hommey <mh+mozilla@glandium.org>
Mon, 13 Feb 2012 15:48:23 +0100
changeset 90070 71d144fbd53e8983f0a0e8049aa340c8f3d26426
parent 90069 91f55e5ac0adc2470eb589a4acb207a26248addf
child 90071 91d77c934b264f3b93346aa113ad957e160074de
push id136
push userlsblakk@mozilla.com
push dateFri, 01 Jun 2012 02:39:32 +0000
treeherdermozilla-release@7ebf7352c959 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswaldo, khuey
bugs717540
milestone13.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 717540 - Remove MFBT dependency on JS_Assert, add MOZ_Assert, and use it for WTF assertions. r=waldo,r=khuey
config/config.mk
config/rules.mk
configure.in
js/src/Makefile.in
js/src/assembler/assembler/MacroAssemblerX86Common.h
js/src/assembler/wtf/Assertions.h
js/src/config/config.mk
js/src/config/rules.mk
js/src/jsapi-tests/Makefile.in
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsinfer.cpp
js/src/jsutil.cpp
js/src/jsutil.h
js/src/shell/Makefile.in
js/src/vm/Stack.cpp
mfbt/Assertions.cpp
mfbt/Assertions.h
mfbt/GuardObjects.h
mfbt/Makefile.in
mfbt/Types.h
mfbt/sources.mk
mozglue/build/Makefile.in
--- a/config/config.mk
+++ b/config/config.mk
@@ -251,17 +251,19 @@ endif # MOZ_DEBUG
 # the Makefile wants static CRT linking.
 ifeq ($(MOZ_MEMORY)_$(USE_STATIC_LIBS),1_1)
 # Disable default CRT libs and add the right lib path for the linker
 MOZ_GLUE_LDFLAGS=
 endif
 
 endif # WINNT && !GNU_CC
 
-ifndef MOZ_GLUE_PROGRAM_LDFLAGS
+ifdef MOZ_GLUE_PROGRAM_LDFLAGS
+DEFINES += -DMOZ_GLUE_IN_PROGRAM
+else
 MOZ_GLUE_PROGRAM_LDFLAGS=$(MOZ_GLUE_LDFLAGS)
 endif
 
 #
 # Build using PIC by default
 #
 _ENABLE_PIC=1
 
@@ -805,8 +807,26 @@ OBJ_SUFFIX := $(_OBJ_SUFFIX)
 # for the first pass.
 ifndef NO_PROFILE_GUIDED_OPTIMIZE
 ifdef MOZ_PROFILE_GENERATE
 ifdef GNU_CC
 OBJ_SUFFIX := i_o
 endif
 endif
 endif
+
+# EXPAND_LIBNAME - $(call EXPAND_LIBNAME,foo)
+# expands to $(LIB_PREFIX)foo.$(LIB_SUFFIX) or -lfoo, depending on linker
+# arguments syntax. Should only be used for system libraries
+
+# EXPAND_LIBNAME_PATH - $(call EXPAND_LIBNAME_PATH,foo,dir)
+# expands to dir/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
+
+# EXPAND_MOZLIBNAME - $(call EXPAND_MOZLIBNAME,foo)
+# expands to $(DIST)/lib/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
+
+ifdef GNU_CC
+EXPAND_LIBNAME = $(addprefix -l,$(1))
+else
+EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+endif
+EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -87,34 +87,16 @@ endif
 _VPATH_SRCS = $(abspath $<)
 
 # Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
 VPATH += $(DIST)/lib
 ifdef LIBXUL_SDK
 VPATH += $(LIBXUL_SDK)/lib
 endif
 
-# EXPAND_LIBNAME - $(call EXPAND_LIBNAME,foo)
-# expands to $(LIB_PREFIX)foo.$(LIB_SUFFIX) or -lfoo, depending on linker
-# arguments syntax. Should only be used for system libraries
-
-# EXPAND_LIBNAME_PATH - $(call EXPAND_LIBNAME_PATH,foo,dir)
-# expands to dir/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
-
-# EXPAND_MOZLIBNAME - $(call EXPAND_MOZLIBNAME,foo)
-# expands to $(DIST)/lib/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
-
-ifdef GNU_CC
-EXPAND_LIBNAME = $(addprefix -l,$(1))
-else
-EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
-endif
-EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
-EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
-
 ifdef EXTRA_DSO_LIBS
 EXTRA_DSO_LIBS	:= $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS))
 endif
 
 ################################################################################
 # Testing frameworks support
 ################################################################################
 
--- a/configure.in
+++ b/configure.in
@@ -9122,22 +9122,22 @@ if test -z "$MOZ_NATIVE_NSPR"; then
     ac_configure_args="$ac_configure_args --with-nspr-cflags='$NSPR_CFLAGS'"
     ac_configure_args="$ac_configure_args --with-nspr-libs='$NSPR_LIBS'"
 fi
 ac_configure_args="$ac_configure_args --with-dist-dir=../../dist"
 ac_configure_args="$ac_configure_args --prefix=$dist"
 ac_configure_args="$ac_configure_args --with-sync-build-files=$_topsrcdir"
 if test "$MOZ_MEMORY"; then
    ac_configure_args="$ac_configure_args --enable-jemalloc"
-   if test -n "$MOZ_GLUE_LDFLAGS"; then
-     export MOZ_GLUE_LDFLAGS
-   fi
-   if test -n "$MOZ_GLUE_PROGRAM_LDFLAGS"; then
-     export MOZ_GLUE_PROGRAM_LDFLAGS
-   fi
+fi
+if test -n "$MOZ_GLUE_LDFLAGS"; then
+   export MOZ_GLUE_LDFLAGS
+fi
+if test -n "$MOZ_GLUE_PROGRAM_LDFLAGS"; then
+   export MOZ_GLUE_PROGRAM_LDFLAGS
 fi
 export MOZ_APP_NAME
 AC_OUTPUT_SUBDIRS(js/src)
 ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 
 fi # COMPILE_ENVIRONMENT && !LIBXUL_SDK_DIR
 
 dnl Prevent the regeneration of autoconf.mk forcing rebuilds of the world
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -362,18 +362,17 @@ ENABLE_YARR_JIT = 1
 VPATH += 	$(srcdir)/assembler \
 		$(srcdir)/assembler/wtf \
 		$(srcdir)/assembler/jit \
 		$(srcdir)/assembler/assembler \
 		$(srcdir)/methodjit \
 		$(srcdir)/yarr \
 		$(NONE)
 
-CPPSRCS += 	Assertions.cpp \
-		ExecutableAllocator.cpp \
+CPPSRCS += 	ExecutableAllocator.cpp \
 		ARMAssembler.cpp \
 		MacroAssemblerARM.cpp \
 		MacroAssemblerX86Common.cpp \
 		PageBlock.cpp \
 		YarrInterpreter.cpp \
 		YarrJIT.cpp \
 		YarrPattern.cpp \
 		YarrSyntaxChecker.cpp \
@@ -485,16 +484,23 @@ ifneq (,$(filter 1400 1500,$(_MSC_VER)))
 ifeq ($(OS_TEST),x86_64)
 ASFILES += jswin64.asm
 endif
 endif
 endif
 
 include $(topsrcdir)/config/config.mk
 
+ifeq (,$(MOZ_GLUE_PROGRAM_LDFLAGS))
+# When building standalone, we need to include mfbt sources, and to declare
+# "exported" mfbt symbols on its behalf when we use its headers.
+include $(srcdir)/../../mfbt/sources.mk
+DEFINES += -DIMPL_MFBT
+endif
+
 EXTRA_DSO_LDOPTS += $(NSPR_LIBS)
 
 ifndef BUILD_OPT
 MOCHAFILE	= 1
 endif
 
 # Define keyword generator before rules.mk, see bug 323979 comment 50
 
@@ -664,21 +670,16 @@ DIST_GARBAGE = config.cache config.log c
    unallmakefiles js-config js-config.h js-confdefs.h
 
 distclean::
 	cat unallmakefiles | $(XARGS) rm -f
 	$(RM) $(DIST_GARBAGE)
 
 DEFINES		+= -DEXPORT_JS_API
 
-# mfbt is always packed with us, so if we're building a shared object,
-# we need to declare "exported" mfbt symbols on its behalf when we use
-# its headers.
-DEFINES		+= -DIMPL_MFBT
-
 INCLUDES	+= -I$(srcdir)
 
 ifdef JS_THREADSAFE
 DEFINES		+= -DJS_THREADSAFE
 endif
 
 ifdef JS_HAS_CTYPES
 DEFINES		+= -DJS_HAS_CTYPES
--- a/js/src/assembler/assembler/MacroAssemblerX86Common.h
+++ b/js/src/assembler/assembler/MacroAssemblerX86Common.h
@@ -86,19 +86,21 @@ public:
         // If either operand is NaN, these conditions always evaluate to true.
         DoubleEqualOrUnordered = X86Assembler::ConditionE,
         DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
         DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
         DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
         DoubleLessThanOrUnordered = X86Assembler::ConditionB,
         DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE
     };
-    COMPILE_ASSERT(
-        !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
-        DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
+    static void staticAsserts() {
+        COMPILE_ASSERT(
+            !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
+            DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
+    }
 
     static const RegisterID stackPointerRegister = X86Registers::esp;
 
     static inline bool CanUse8Bit(RegisterID reg) {
         return !!((1 << reg) & ~((1 << X86Registers::esp) |
                                  (1 << X86Registers::edi) |
                                  (1 << X86Registers::esi) |
                                  (1 << X86Registers::ebp)));
--- a/js/src/assembler/wtf/Assertions.h
+++ b/js/src/assembler/wtf/Assertions.h
@@ -21,16 +21,28 @@
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
 #ifndef WTF_Assertions_h
 #define WTF_Assertions_h
 
+#include "Platform.h"
+#include "mozilla/Assertions.h"
+
+#define ASSERT(assertion) MOZ_ASSERT(assertion)
+#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
+#define ASSERT_NOT_REACHED() MOZ_NOT_REACHED("")
+#define CRASH() MOZ_Crash()
+#define COMPILE_ASSERT(exp, name) MOZ_STATIC_ASSERT(exp, #name)
+
+#endif
+
+#if 0
 /*
    no namespaces because this file has to be includable from C and Objective-C
 
    Note, this file uses many GCC extensions, but it should be compatible with
    C, Objective C, C++, and Objective C++.
 
    For non-debug builds, everything is disabled by default.
    Defining any of the symbols explicitly prevents this from having any effect.
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -251,17 +251,19 @@ endif # MOZ_DEBUG
 # the Makefile wants static CRT linking.
 ifeq ($(MOZ_MEMORY)_$(USE_STATIC_LIBS),1_1)
 # Disable default CRT libs and add the right lib path for the linker
 MOZ_GLUE_LDFLAGS=
 endif
 
 endif # WINNT && !GNU_CC
 
-ifndef MOZ_GLUE_PROGRAM_LDFLAGS
+ifdef MOZ_GLUE_PROGRAM_LDFLAGS
+DEFINES += -DMOZ_GLUE_IN_PROGRAM
+else
 MOZ_GLUE_PROGRAM_LDFLAGS=$(MOZ_GLUE_LDFLAGS)
 endif
 
 #
 # Build using PIC by default
 #
 _ENABLE_PIC=1
 
@@ -805,8 +807,26 @@ OBJ_SUFFIX := $(_OBJ_SUFFIX)
 # for the first pass.
 ifndef NO_PROFILE_GUIDED_OPTIMIZE
 ifdef MOZ_PROFILE_GENERATE
 ifdef GNU_CC
 OBJ_SUFFIX := i_o
 endif
 endif
 endif
+
+# EXPAND_LIBNAME - $(call EXPAND_LIBNAME,foo)
+# expands to $(LIB_PREFIX)foo.$(LIB_SUFFIX) or -lfoo, depending on linker
+# arguments syntax. Should only be used for system libraries
+
+# EXPAND_LIBNAME_PATH - $(call EXPAND_LIBNAME_PATH,foo,dir)
+# expands to dir/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
+
+# EXPAND_MOZLIBNAME - $(call EXPAND_MOZLIBNAME,foo)
+# expands to $(DIST)/lib/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
+
+ifdef GNU_CC
+EXPAND_LIBNAME = $(addprefix -l,$(1))
+else
+EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+endif
+EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -87,34 +87,16 @@ endif
 _VPATH_SRCS = $(abspath $<)
 
 # Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
 VPATH += $(DIST)/lib
 ifdef LIBXUL_SDK
 VPATH += $(LIBXUL_SDK)/lib
 endif
 
-# EXPAND_LIBNAME - $(call EXPAND_LIBNAME,foo)
-# expands to $(LIB_PREFIX)foo.$(LIB_SUFFIX) or -lfoo, depending on linker
-# arguments syntax. Should only be used for system libraries
-
-# EXPAND_LIBNAME_PATH - $(call EXPAND_LIBNAME_PATH,foo,dir)
-# expands to dir/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
-
-# EXPAND_MOZLIBNAME - $(call EXPAND_MOZLIBNAME,foo)
-# expands to $(DIST)/lib/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
-
-ifdef GNU_CC
-EXPAND_LIBNAME = $(addprefix -l,$(1))
-else
-EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
-endif
-EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
-EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
-
 ifdef EXTRA_DSO_LIBS
 EXTRA_DSO_LIBS	:= $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS))
 endif
 
 ################################################################################
 # Testing frameworks support
 ################################################################################
 
--- a/js/src/jsapi-tests/Makefile.in
+++ b/js/src/jsapi-tests/Makefile.in
@@ -100,16 +100,19 @@ CSRCS = \
 # given the test's dependence on interactions between the compiler, the GC, and
 # conservative stack scanning, the fix isn't obvious: more investigation
 # needed.
 #CPPSRCS += \
 #  testRegExpInstanceProperties.cpp \
 #  $(NULL)
 
 DEFINES         += -DEXPORT_JS_API
+# Building against js_static requires that we declare mfbt sybols "exported"
+# on its behalf.
+DEFINES         += -DIMPL_MFBT
 
 LIBS      = $(DEPTH)/$(LIB_PREFIX)js_static.$(LIB_SUFFIX) $(NSPR_LIBS)
 
 LOCAL_INCLUDES += -I$(topsrcdir) -I..
 
 include $(topsrcdir)/config/rules.mk
 
 check::
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6596,17 +6596,17 @@ JS_SetRuntimeThread(JSRuntime *rt)
 #endif
 }
 
 extern JS_NEVER_INLINE JS_PUBLIC_API(void)
 JS_AbortIfWrongThread(JSRuntime *rt)
 {
 #ifdef JS_THREADSAFE
     if (!rt->onOwnerThread())
-        JS_Assert("rt->onOwnerThread()", __FILE__, __LINE__);
+        MOZ_Assert("rt->onOwnerThread()", __FILE__, __LINE__);
 #endif
 }
 
 #ifdef JS_GC_ZEAL
 JS_PUBLIC_API(void)
 JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency, JSBool compartment)
 {
     bool schedule = zeal >= js::gc::ZealAllocThreshold && zeal < js::gc::ZealVerifierThreshold;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -65,16 +65,18 @@
 
 /* JS::Value can store a full int32_t. */
 #define JSVAL_INT_BITS          32
 #define JSVAL_INT_MIN           ((jsint)0x80000000)
 #define JSVAL_INT_MAX           ((jsint)0x7fffffff)
 
 /************************************************************************/
 
+#define JS_Assert MOZ_Assert
+
 #ifdef __cplusplus
 namespace JS {
 
 /*
  * Protecting non-jsval, non-JSObject *, non-JSString * values from collection
  *
  * Most of the time, the garbage collector's conservative stack scanner works
  * behind the scenes, finding all live values and protecting them from being
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -344,17 +344,17 @@ types::TypeFailure(JSContext *cx, const 
     va_end(ap);
 
     JS_snprintf(msgbuf, sizeof(msgbuf), "[infer failure] %s", errbuf);
 
     /* Dump type state, even if INFERFLAGS is unset. */
     cx->compartment->types.print(cx, true);
 
     /* Always active, even in release builds */
-    JS_Assert(msgbuf, __FILE__, __LINE__);
+    MOZ_Assert(msgbuf, __FILE__, __LINE__);
     
     *((volatile int *)NULL) = 0;  /* Should never be reached */
 }
 
 /////////////////////////////////////////////////////////////////////
 // TypeSet
 /////////////////////////////////////////////////////////////////////
 
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -64,61 +64,24 @@ 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 (*)()));
 
-static JS_NEVER_INLINE void
-CrashInJS()
-{
-    /*
-     * We write 123 here so that the machine code for this function is
-     * unique. Otherwise the linker, trying to be smart, might use the
-     * same code for CrashInJS and for some other function. That
-     * messes up the signature in minidumps.
-     */
-
-#if defined(WIN32)
-    /*
-     * We used to call DebugBreak() on Windows, but amazingly, it causes
-     * the MSVS 2010 debugger not to be able to recover a call stack.
-     */
-    *((volatile int *) NULL) = 123;
-    exit(3);
-#elif defined(__APPLE__)
-    /*
-     * On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
-     * trapped.
-     */
-    *((volatile int *) NULL) = 123;  /* To continue from here in GDB: "return" then "continue". */
-    raise(SIGABRT);  /* In case above statement gets nixed by the optimizer. */
-#else
-    raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */
-#endif
-}
-
 /*
  * |JS_Assert| historically took |JSIntn ln| as its last argument.  We've
  * boiled |JSIntn ln| down to simply |int ln| so that mfbt may declare the
  * function without depending on the |JSIntn| typedef, so we must manually
  * verify that the |JSIntn| typedef is consistent.
  */
 JS_STATIC_ASSERT((tl::IsSameType<JSIntn, int>::result));
 
-JS_PUBLIC_API(void)
-JS_Assert(const char *s, const char *file, int ln)
-{
-    fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
-    fflush(stderr);
-    CrashInJS();
-}
-
 #ifdef JS_BASIC_STATS
 
 #include <math.h>
 #include <string.h>
 #include "jscompat.h"
 
 /*
  * Histogram bins count occurrences of values <= the bin label, as follows:
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -326,19 +326,19 @@ inline __attribute__ ((unused)) void MUS
 
 /* Crash diagnostics */
 #ifdef DEBUG
 # define JS_CRASH_DIAGNOSTICS 1
 #endif
 #ifdef JS_CRASH_DIAGNOSTICS
 # define JS_POISON(p, val, size) memset((p), (val), (size))
 # define JS_OPT_ASSERT(expr)                                                  \
-    ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
+    ((expr) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
 # define JS_OPT_ASSERT_IF(cond, expr)                                         \
-    ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
+    ((!(cond) || (expr)) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
 #else
 # define JS_POISON(p, val, size) ((void) 0)
 # define JS_OPT_ASSERT(expr) ((void) 0)
 # define JS_OPT_ASSERT_IF(cond, expr) ((void) 0)
 #endif
 
 /* Basic stats */
 #ifdef DEBUG
--- a/js/src/shell/Makefile.in
+++ b/js/src/shell/Makefile.in
@@ -48,16 +48,19 @@ PROGRAM         = js$(BIN_SUFFIX)
 CPPSRCS		= \
   js.cpp \
   jsworkers.cpp \
   jsoptparse.cpp \
   jsheaptools.cpp \
   $(NULL)
 
 DEFINES         += -DEXPORT_JS_API
+# Building against js_static requires that we declare mfbt sybols "exported"
+# on its behalf.
+DEFINES         += -DIMPL_MFBT
 
 LIBS      = $(NSPR_LIBS) $(EDITLINE_LIBS) $(DEPTH)/$(LIB_PREFIX)js_static.$(LIB_SUFFIX)
 ifdef MOZ_NATIVE_FFI
 EXTRA_LIBS += $(MOZ_FFI_LIBS)
 endif
 
 LOCAL_INCLUDES += -I$(topsrcdir) -I..
 
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1047,17 +1047,17 @@ StackIter::startOnSegment(StackSegment *
 }
 
 static void JS_NEVER_INLINE
 CrashIfInvalidSlot(StackFrame *fp, Value *vp)
 {
     if (vp < fp->slots() || vp >= fp->slots() + fp->script()->nslots) {
         JS_ASSERT(false && "About to dereference invalid slot");
         *(int *)0xbad = 0;  // show up nicely in crash-stats
-        JS_Assert("About to dereference invalid slot", __FILE__, __LINE__);
+        MOZ_Assert("About to dereference invalid slot", __FILE__, __LINE__);
     }
 }
 
 void
 StackIter::settleOnNewState()
 {
     /*
      * There are elements of the calls_ and fp_ chains that we want to skip
new file mode 100644
--- /dev/null
+++ b/mfbt/Assertions.cpp
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mike Hommey <mh@glandium.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * 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 ***** */
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Types.h"
+
+#include <cstdio>
+#include <cstdlib>
+#ifndef WIN32
+#include <signal.h>
+#endif
+
+/* Implementations of runtime and static assertion macros for C and C++. */
+
+extern "C" {
+
+MOZ_EXPORT_API(void)
+MOZ_Crash()
+{
+  /*
+   * We write 123 here so that the machine code for this function is
+   * unique. Otherwise the linker, trying to be smart, might use the
+   * same code for MOZ_Crash and for some other function. That
+   * messes up the signature in minidumps.
+   */
+
+#if defined(WIN32)
+  /*
+   * We used to call DebugBreak() on Windows, but amazingly, it causes
+   * the MSVS 2010 debugger not to be able to recover a call stack.
+   */
+  *((volatile int *) NULL) = 123;
+  exit(3);
+#elif defined(__APPLE__)
+  /*
+   * On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
+   * trapped.
+   */
+  *((volatile int *) NULL) = 123;  /* To continue from here in GDB: "return" then "continue". */
+  raise(SIGABRT);  /* In case above statement gets nixed by the optimizer. */
+#else
+  raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */
+#endif
+}
+
+MOZ_EXPORT_API(void)
+MOZ_Assert(const char* s, const char* file, int ln)
+{
+  fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
+  fflush(stderr);
+  MOZ_Crash();
+}
+
+}
--- a/mfbt/Assertions.h
+++ b/mfbt/Assertions.h
@@ -121,36 +121,25 @@
 #  else
 #    define MOZ_STATIC_ASSERT(cond, reason) \
        extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1])
 #  endif
 #endif
 
 #define MOZ_STATIC_ASSERT_IF(cond, expr, reason)  MOZ_STATIC_ASSERT(!(cond) || (expr), reason)
 
-/*
- * XXX: we're cheating here in order to avoid creating object files
- * for mfbt /just/ to provide a function like FatalError() to be used
- * by MOZ_ASSERT().  (It'll happen eventually, but for just ASSERT()
- * it isn't worth the pain.)  JS_Assert(), although unfortunately
- * named, is part of SpiderMonkey's stable, external API, so this
- * isn't quite as bad as it seems.
- *
- * Once mfbt needs object files, this unholy union with JS_Assert()
- * will be broken.
- *
- * JS_Assert is present even in release builds, for the benefit of applications
- * that build DEBUG and link against a non-DEBUG SpiderMonkey library.
- */
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 extern MFBT_API(void)
-JS_Assert(const char* s, const char* file, int ln);
+MOZ_Crash(void);
+
+extern MFBT_API(void)
+MOZ_Assert(const char* s, const char* file, int ln);
 
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
 /*
  * MOZ_ASSERT(expr [, explanation-string]) asserts that |expr| must be truthy in
  * debug builds.  If it is, execution continues.  Otherwise, an error message
@@ -181,20 +170,20 @@ JS_Assert(const char* s, const char* fil
  *              "we already set [[PrimitiveThis]] for this String object");
  *
  * MOZ_ASSERT has no effect in non-debug builds.  It is designed to catch bugs
  * *only* during debugging, not "in the field".
  */
 #ifdef DEBUG
    /* First the single-argument form. */
 #  define MOZ_ASSERT_HELPER1(expr) \
-     ((expr) ? ((void)0) : JS_Assert(#expr, __FILE__, __LINE__))
+     ((expr) ? ((void)0) : MOZ_Assert(#expr, __FILE__, __LINE__))
    /* Now the two-argument form. */
 #  define MOZ_ASSERT_HELPER2(expr, explain) \
-     ((expr) ? ((void)0) : JS_Assert(#expr " (" explain ")", __FILE__, __LINE__))
+     ((expr) ? ((void)0) : MOZ_Assert(#expr " (" explain ")", __FILE__, __LINE__))
    /* And now, helper macrology up the wazoo. */
    /* Count the number of arguments passed to MOZ_ASSERT. */
 #  define MOZ_COUNT_ASSERT_ARGS(...) \
      MOZ_COUNT_ASSERT_ARGS_IMPL(__VA_ARGS__, 2, 1, 0)
 #  define MOZ_COUNT_ASSERT_ARGS_IMPL(_1, _2, count, ...) \
      count
    /* Invoke the right helper. */
 #  define MOZ_ASSERT_VAHELP2(count, ...) MOZ_ASSERT_HELPER##count(__VA_ARGS__)
@@ -234,17 +223,17 @@ JS_Assert(const char* s, const char* fil
  *       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__)
+#  define MOZ_NOT_REACHED(reason)    MOZ_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
--- a/mfbt/GuardObjects.h
+++ b/mfbt/GuardObjects.h
@@ -95,34 +95,34 @@ namespace detail {
  *     a base class that also uses these macros
  *   MOZ_GUARD_OBJECT_NOTIFIER_INIT is a statement that belongs in each
  *     constructor. It uses the parameter declared by
  *     MOZ_GUARD_OBJECT_NOTIFIER_PARAM.
  *
  * For more details, and examples of using these macros, see
  * https://developer.mozilla.org/en/Using_RAII_classes_in_Mozilla
  */
-class MFBT_API(GuardObjectNotifier)
+class MOZ_EXPORT_API(GuardObjectNotifier)
 {
   private:
     bool* statementDone;
 
   public:
     GuardObjectNotifier() : statementDone(NULL) {}
 
     ~GuardObjectNotifier() {
         *statementDone = true;
     }
 
     void setStatementDone(bool* statementIsDone) {
         statementDone = statementIsDone;
     }
 };
 
-class MFBT_API(GuardObjectNotificationReceiver)
+class MOZ_EXPORT_API(GuardObjectNotificationReceiver)
 {
   private:
     bool statementDone;
 
   public:
     GuardObjectNotificationReceiver() : statementDone(false) {}
 
     ~GuardObjectNotificationReceiver() {
--- a/mfbt/Makefile.in
+++ b/mfbt/Makefile.in
@@ -37,16 +37,28 @@
 
 DEPTH = ..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
+MODULE = mozglue
+LIBRARY_NAME = mfbt
+FORCE_STATIC_LIB = 1
+STL_FLAGS =
+
 DIRS =
 
 # exported_headers.mk defines the headers exported by mfbt.  It is included by
 # mfbt itself and by the JS engine, which, when built standalone, must do the
 # work to install mfbt's exported headers itself.
 include $(srcdir)/exported_headers.mk
 
+# sources.mk defines the source files built for mfbt. It is included by mfbt
+# itself and by the JS engine, which, when built standalone, must do the work
+# to build mfbt sources itself.
+include $(srcdir)/sources.mk
+
+DEFINES += -DIMPL_MFBT
+
 include $(topsrcdir)/config/rules.mk
--- a/mfbt/Types.h
+++ b/mfbt/Types.h
@@ -124,18 +124,27 @@
  * Consistent with the above comment, the MFBT_API and MFBT_DATA macros expose
  * export mfbt declarations when building mfbt, and they expose import mfbt
  * declarations when using mfbt.
  */
 #if defined(IMPL_MFBT)
 #  define MFBT_API(type)        MOZ_EXPORT_API(type)
 #  define MFBT_DATA(type)       MOZ_EXPORT_DATA(type)
 #else
-#  define MFBT_API(type)        MOZ_IMPORT_API(type)
-#  define MFBT_DATA(type)       MOZ_IMPORT_DATA(type)
+  /*
+   * When mozglue is linked in the program, we need the MFBT API symbols
+   * to be weak.
+   */
+#  if defined(MOZ_GLUE_IN_PROGRAM)
+#    define MFBT_API(type)        __attribute__((weak)) MOZ_IMPORT_API(type)
+#    define MFBT_DATA(type)       __attribute__((weak)) MOZ_IMPORT_DATA(type)
+#  else
+#    define MFBT_API(type)        MOZ_IMPORT_API(type)
+#    define MFBT_DATA(type)       MOZ_IMPORT_DATA(type)
+#  endif
 #endif
 
 /*
  * C symbols in C++ code must be declared immediately within |extern "C"|
  * blocks.  However, in C code, they need not be declared specially.  This
  * difference is abstracted behind the MOZ_BEGIN_EXTERN_C and MOZ_END_EXTERN_C
  * macros, so that the user need not know whether he is being used in C or C++
  * code.
new file mode 100644
--- /dev/null
+++ b/mfbt/sources.mk
@@ -0,0 +1,3 @@
+CPPSRCS += \
+  Assertions.cpp \
+  $(NULL)
--- a/mozglue/build/Makefile.in
+++ b/mozglue/build/Makefile.in
@@ -88,16 +88,18 @@ SHARED_LIBRARY_LIBS += $(call EXPAND_LIB
 SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,android,../android)
 endif
 
 ifdef MOZ_LINKER
 # Add custom dynamic linker
 SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,linker,../linker)
 endif
 
+SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,mfbt,$(DEPTH)/mfbt)
+
 ifeq (Android, $(OS_TARGET))
 WRAP_LDFLAGS =
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 ifdef MOZ_MEMORY
 ifeq (Darwin,$(OS_TARGET))