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 89679 71d144fbd53e8983f0a0e8049aa340c8f3d26426
parent 89678 91f55e5ac0adc2470eb589a4acb207a26248addf
child 89680 91d77c934b264f3b93346aa113ad957e160074de
push idunknown
push userunknown
push dateunknown
reviewerswaldo, khuey
bugs717540
milestone13.0a1
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))