Bug 515492: Make jemalloc work on VS 2010. r=ted,pbiggar
authorKyle Huey <khuey@kylehuey.com>
Mon, 27 Jun 2011 12:44:51 -0700
changeset 71921 d77cddcc9bd699e0d1ee209cbc0099b6acd54427
parent 71920 bf88ac3f2316eb1c90318e69616063c68dbd9988
child 71922 929f956a1a42383069d55b4ffeaf2fa3f084bb25
push id289
push userjdrew@mozilla.com
push dateTue, 28 Jun 2011 16:21:21 +0000
treeherdermozilla-inbound@35178797a902 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted, pbiggar
bugs515492
milestone7.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 515492: Make jemalloc work on VS 2010. r=ted,pbiggar
browser/installer/Makefile.in
browser/installer/package-manifest.in
config/autoconf.mk.in
config/config.mk
config/rules.mk
configure.in
js/src/config/config.mk
js/src/config/rules.mk
memory/jemalloc/Makefile.in
memory/jemalloc/fixcrt.py
memory/jemalloc/jemalloc.c
memory/jemalloc/jemalloc.def
memory/jemalloc/jemalloc.h
memory/mozalloc/mozalloc.cpp
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -83,16 +83,20 @@ ifdef MOZ_ANGLE
 DEFINES += -DMOZ_ANGLE=$(MOZ_ANGLE)
 DEFINES += -DMOZ_D3DX9_DLL=$(MOZ_D3DX9_DLL)
 DEFINES += -DMOZ_D3DCOMPILER_DLL=$(MOZ_D3DCOMPILER_DLL)
 endif
 
 include $(topsrcdir)/ipc/app/defs.mk
 DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME)
 
+ifdef WIN32_OLD_STYLE_JEMALLOC
+DEFINES += -DWIN32_OLD_STYLE_JEMALLOC=1
+endif
+
 ifdef MOZ_PKG_MANIFEST_P
 MOZ_PKG_MANIFEST = package-manifest
 
 $(MOZ_PKG_MANIFEST): $(MOZ_PKG_MANIFEST_P)
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $< > $@
 
 GARBAGE += $(MOZ_PKG_MANIFEST)
 endif
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -58,35 +58,38 @@
 #endif
 #ifdef XP_MACOSX
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@.app/
 @BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
 #else
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@
 #endif
 #ifdef XP_WIN32
-#ifndef MOZ_MEMORY
+#ifdef MOZ_MEMORY
+#ifdef WIN32_OLD_STYLE_JEMALLOC
+@BINPATH@/mozcrt19.dll
+@BINPATH@/mozcpp19.dll
+#endif
+#endif
+#else
 #if _MSC_VER == 1400
 @BINPATH@/Microsoft.VC80.CRT.manifest
 @BINPATH@/msvcm80.dll
 @BINPATH@/msvcp80.dll
 @BINPATH@/msvcr80.dll
 #elif _MSC_VER == 1500
 @BINPATH@/Microsoft.VC90.CRT.manifest
 @BINPATH@/msvcm90.dll
 @BINPATH@/msvcp90.dll
 @BINPATH@/msvcr90.dll
 #elif _MSC_VER == 1600
 @BINPATH@/msvcp100.dll
 @BINPATH@/msvcr100.dll
 #endif
-#else
-@BINPATH@/mozcrt19.dll
-@BINPATH@/mozcpp19.dll
-#endif
+
 #endif
 
 [browser]
 ; [Base Browser Files]
 #ifndef XP_UNIX
 @BINPATH@/@MOZ_APP_NAME@.exe
 #else
 @BINPATH@/@MOZ_APP_NAME@-bin
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -628,16 +628,18 @@ MOZILLA_OFFICIAL = @MOZILLA_OFFICIAL@
 # Win32 options
 MOZ_BROWSE_INFO	= @MOZ_BROWSE_INFO@
 MOZ_TOOLS_DIR	= @MOZ_TOOLS_DIR@
 MOZ_QUANTIFY	= @MOZ_QUANTIFY@
 MSMANIFEST_TOOL = @MSMANIFEST_TOOL@
 WIN32_REDIST_DIR = @WIN32_REDIST_DIR@
 WIN32_CRT_SRC_DIR = @WIN32_CRT_SRC_DIR@
 MOZ_MEMORY_LDFLAGS = @MOZ_MEMORY_LDFLAGS@
+WIN32_OLD_STYLE_JEMALLOC = @WIN32_OLD_STYLE_JEMALLOC@
+WIN32_CRT_LIBS = @WIN32_CRT_LIBS@
 MOZ_CRT_CPU_ARCH = @MOZ_CRT_CPU_ARCH@
 
 # This is for custom CRT building
 ifdef MOZ_MEMORY
 ifdef WIN32_CRT_SRC_DIR
 DLLFLAGS = @DLLFLAGS@
 endif
 endif
--- a/config/config.mk
+++ b/config/config.mk
@@ -190,24 +190,16 @@ OS_LDFLAGS += $(_DEBUG_LDFLAGS)
 ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
 ifdef MOZ_DEBUG
 ifneq (,$(MOZ_BROWSE_INFO)$(MOZ_BSCFILE))
 OS_CFLAGS += -FR
 OS_CXXFLAGS += -FR
 endif
 else # ! MOZ_DEBUG
 
-# We don't build a static CRT when building a custom CRT,
-# it appears to be broken. So don't link to jemalloc if
-# the Makefile wants static CRT linking.
-ifeq ($(MOZ_MEMORY)_$(USE_STATIC_LIBS),1_)
-# Disable default CRT libs and add the right lib path for the linker
-OS_LDFLAGS += $(MOZ_MEMORY_LDFLAGS)
-endif
-
 # MOZ_DEBUG_SYMBOLS generates debug symbols in separate PDB files.
 # Used for generating an optimized build with debugging symbols.
 # Used in the Windows nightlies to generate symbols for crash reporting.
 ifdef MOZ_DEBUG_SYMBOLS
 OS_CXXFLAGS += -Zi -UDEBUG -DNDEBUG
 OS_CFLAGS += -Zi -UDEBUG -DNDEBUG
 ifdef HAVE_64BIT_OS
 OS_LDFLAGS += -DEBUG -OPT:REF,ICF
@@ -236,16 +228,25 @@ MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDE
 ifdef HAVE_64BIT_OS
 OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF,ICF
 else
 OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF
 endif
 endif # NS_TRACE_MALLOC
 
 endif # MOZ_DEBUG
+
+# We don't build a static CRT when building a custom CRT,
+# it appears to be broken. So don't link to jemalloc if
+# the Makefile wants static CRT linking.
+ifeq ($(MOZ_MEMORY)_$(USE_STATIC_LIBS),1_)
+# Disable default CRT libs and add the right lib path for the linker
+OS_LDFLAGS += $(MOZ_MEMORY_LDFLAGS)
+endif
+
 endif # WINNT && !GNU_CC
 
 #
 # Build using PIC by default
 #
 _ENABLE_PIC=1
 
 # Determine if module being compiled is destined 
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -833,17 +833,19 @@ ifdef IS_COMPONENT
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
 	$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
 ifndef NO_COMPONENTS_MANIFEST
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
 endif
 else # ! IS_COMPONENT
 ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
+ifndef NO_INSTALL_IMPORT_LIBRARY
 	$(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(DIST)/lib
+endif
 else
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DIST)/lib
 endif
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)
 endif # IS_COMPONENT
 endif # SHARED_LIBRARY
 ifdef PROGRAM
 	$(INSTALL) $(IFLAGS2) $(PROGRAM) $(FINAL_TARGET)
--- a/configure.in
+++ b/configure.in
@@ -7380,20 +7380,26 @@ else
     AC_DEFINE(MOZ_MEMORY_BSD)
     ;;
   *-solaris*)
     AC_DEFINE(MOZ_MEMORY_SOLARIS)
     ;;
   *-mingw*)
     AC_DEFINE(MOZ_MEMORY_WINDOWS)
     dnl This is sort of awful. Will revisit if we add support for more versions
-    if test "$CC_VERSION" != "14.00.50727.762" -a "$CC_VERSION" != "15.00.30729.01"; then
-        AC_MSG_ERROR([Building jemalloc requires exactly Visual C++ 2005 SP1 or 2008 SP1 currently.])
-    fi
-    if test -z "$WIN32_CRT_SRC_DIR"; then
+    if test "$CC_VERSION" == "14.00.50727.762" -o "$CC_VERSION" == "15.00.30729.01"; then
+      WIN32_OLD_STYLE_JEMALLOC=1
+      AC_DEFINE(WIN32_OLD_STYLE_JEMALLOC)
+    elif test "$CC_VERSION" == "16.00.30319.01" -o "$CC_VERSION" == "16.00.40219.01"; then
+      WIN32_NEW_STYLE_JEMALLOC=1
+      AC_DEFINE(WIN32_NEW_STYLE_JEMALLOC)
+    else        
+      AC_MSG_ERROR([Building jemalloc requires exactly Visual C++ 2005 SP1 or 2008 SP1 or 2010 currently.])
+    fi
+    if test -z "$WIN32_CRT_SRC_DIR" -a -n "$WIN32_OLD_STYLE_JEMALLOC"; then
       if test -z "$VCINSTALLDIR" -o ! -d "$VCINSTALLDIR"; then
         AC_MSG_ERROR([When building jemalloc, set WIN32_CRT_SRC_DIR to the path to the Visual C++ CRT source (usually VCINSTALLDIR\crt\src, but VCINSTALLDIR is not set, so I can't autodetect it for you).])
       else
         WIN32_CRT_SRC_DIR="$VCINSTALLDIR\crt\src"
       fi
     fi
     dnl cpu check
     case "${target_cpu}" in
@@ -7405,23 +7411,32 @@ else
       ;;
     *)
       AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
       ;;
     esac
 
     AC_SUBST(MOZ_CRT_CPU_ARCH)
 
-    if test ! -d "$WIN32_CRT_SRC_DIR"; then
-      AC_MSG_ERROR([Invalid Win32 CRT source directory: ${WIN32_CRT_SRC_DIR}])
-    fi
-    WIN32_CRT_SRC_DIR=`cd "$WIN32_CRT_SRC_DIR" && pwd -W`
-    _objdir_win=`pwd -W`
-    WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/$MOZ_CRT_CPU_ARCH"
-    MOZ_MEMORY_LDFLAGS="-MANIFEST:NO -LIBPATH:\"$WIN32_CUSTOM_CRT_DIR\" -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt19 -DEFAULTLIB:mozcpp19"
+    if test -n "$WIN32_OLD_STYLE_JEMALLOC"; then
+      if test ! -d "$WIN32_CRT_SRC_DIR"; then
+        AC_MSG_ERROR([Invalid Win32 CRT source directory: ${WIN32_CRT_SRC_DIR}])
+      fi
+      WIN32_CRT_SRC_DIR=`cd "$WIN32_CRT_SRC_DIR" && pwd -W`
+      _objdir_win=`pwd -W`
+      WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/$MOZ_CRT_CPU_ARCH"
+      MOZ_MEMORY_LDFLAGS="-MANIFEST:NO -LIBPATH:\"$WIN32_CUSTOM_CRT_DIR\" -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt19 -DEFAULTLIB:mozcpp19"
+    else
+      MOZ_MEMORY_LDFLAGS='-MANIFEST:NO -LIBPATH:$(DIST)/lib -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt'
+      if test -z "$MOZ_DEBUG"; then
+        WIN32_CRT_LIBS="msvcrt.lib msvcprt.lib"
+      else
+        WIN32_CRT_LIBS="msvcrtd.lib msvcprtd.lib"
+      fi
+    fi
     dnl Also pass this to NSPR/NSS
     DLLFLAGS="$DLLFLAGS $MOZ_MEMORY_LDFLAGS"
     export DLLFLAGS
     ;;
   *)
     AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
     ;;
   esac
@@ -7430,16 +7445,18 @@ else
     dnl NB: this must be kept in sync with jemalloc.h
     AC_DEFINE(HAVE_JEMALLOC_VALLOC)
     AC_DEFINE(HAVE_JEMALLOC_POSIX_MEMALIGN)
     AC_DEFINE(HAVE_JEMALLOC_MEMALIGN)
   fi
 fi # MOZ_MEMORY
 AC_SUBST(MOZ_MEMORY)
 AC_SUBST(MOZ_MEMORY_LDFLAGS)
+AC_SUBST(WIN32_OLD_STYLE_JEMALLOC)
+AC_SUBST(WIN32_CRT_LIBS)
 AC_SUBST(WIN32_CRT_SRC_DIR)
 dnl Need to set this for make because NSS doesn't have configure
 AC_SUBST(DLLFLAGS)
 
 dnl ========================================================
 dnl = Use malloc wrapper lib
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(wrap-malloc,
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -190,24 +190,16 @@ OS_LDFLAGS += $(_DEBUG_LDFLAGS)
 ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
 ifdef MOZ_DEBUG
 ifneq (,$(MOZ_BROWSE_INFO)$(MOZ_BSCFILE))
 OS_CFLAGS += -FR
 OS_CXXFLAGS += -FR
 endif
 else # ! MOZ_DEBUG
 
-# We don't build a static CRT when building a custom CRT,
-# it appears to be broken. So don't link to jemalloc if
-# the Makefile wants static CRT linking.
-ifeq ($(MOZ_MEMORY)_$(USE_STATIC_LIBS),1_)
-# Disable default CRT libs and add the right lib path for the linker
-OS_LDFLAGS += $(MOZ_MEMORY_LDFLAGS)
-endif
-
 # MOZ_DEBUG_SYMBOLS generates debug symbols in separate PDB files.
 # Used for generating an optimized build with debugging symbols.
 # Used in the Windows nightlies to generate symbols for crash reporting.
 ifdef MOZ_DEBUG_SYMBOLS
 OS_CXXFLAGS += -Zi -UDEBUG -DNDEBUG
 OS_CFLAGS += -Zi -UDEBUG -DNDEBUG
 ifdef HAVE_64BIT_OS
 OS_LDFLAGS += -DEBUG -OPT:REF,ICF
@@ -236,16 +228,25 @@ MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDE
 ifdef HAVE_64BIT_OS
 OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF,ICF
 else
 OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF
 endif
 endif # NS_TRACE_MALLOC
 
 endif # MOZ_DEBUG
+
+# We don't build a static CRT when building a custom CRT,
+# it appears to be broken. So don't link to jemalloc if
+# the Makefile wants static CRT linking.
+ifeq ($(MOZ_MEMORY)_$(USE_STATIC_LIBS),1_)
+# Disable default CRT libs and add the right lib path for the linker
+OS_LDFLAGS += $(MOZ_MEMORY_LDFLAGS)
+endif
+
 endif # WINNT && !GNU_CC
 
 #
 # Build using PIC by default
 #
 _ENABLE_PIC=1
 
 # Determine if module being compiled is destined 
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -833,17 +833,19 @@ ifdef IS_COMPONENT
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
 	$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
 ifndef NO_COMPONENTS_MANIFEST
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
 endif
 else # ! IS_COMPONENT
 ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
+ifndef NO_INSTALL_IMPORT_LIBRARY
 	$(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(DIST)/lib
+endif
 else
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DIST)/lib
 endif
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)
 endif # IS_COMPONENT
 endif # SHARED_LIBRARY
 ifdef PROGRAM
 	$(INSTALL) $(IFLAGS2) $(PROGRAM) $(FINAL_TARGET)
--- a/memory/jemalloc/Makefile.in
+++ b/memory/jemalloc/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= jemalloc
 
 # jemalloc.c properly uses 'static', so don't burden it with manually exposing
 # symbols.
 VISIBILITY_FLAGS=
 
 ifeq (WINNT,$(OS_TARGET))
+ifdef WIN32_OLD_STYLE_JEMALLOC
 # Building the CRT from source
 CRT_OBJ_DIR = $(CURDIR)/crtsrc
 MOZ_CRT_DLL_NAME = mozcrt19
 MOZ_CRTCPP_DLL_NAME = mozcpp19
 MOZ_CRT_STATIC_LIBS = libcmt libcpmt
 MOZ_CRT_DLL = $(CRT_OBJ_DIR)/build/$(MOZ_CRT_CPU_ARCH)/$(MOZ_CRT_DLL_NAME).dll
 MOZ_CRT_IMPORT_LIB = $(CRT_OBJ_DIR)/build/$(MOZ_CRT_CPU_ARCH)/$(MOZ_CRT_DLL_NAME).lib
 MOZ_CRTCPP_DLL = $(CRT_OBJ_DIR)/build/$(MOZ_CRT_CPU_ARCH)/$(MOZ_CRTCPP_DLL_NAME).dll
@@ -102,16 +103,32 @@ endif
 # never updated the sample.def files; could probably fix if someone
 # were ever bored enough. :-)
 	rm -f $(addsuffix .lib, $(addprefix $(CRT_OBJ_DIR)/build/$(MOZ_CRT_CPU_ARCH)/, $(MOZ_CRT_STATIC_LIBS)))
 	rm -f $(addsuffix .pdb, $(addprefix $(CRT_OBJ_DIR)/build/$(MOZ_CRT_CPU_ARCH)/, $(MOZ_CRT_STATIC_LIBS)))
 
 # but still export jemalloc.h
 EXPORTS = jemalloc.h jemalloc_types.h
 
+else
+
+CSRCS = jemalloc.c
+EXPORTS = jemalloc.h jemalloc_types.h
+LIBRARY_NAME = jemalloc
+FORCE_SHARED_LIB = 1
+
+MOZ_MEMORY_LDFLAGS = # Don't link against ourselves
+
+DEFFILE = $(srcdir)/jemalloc.def
+
+LDFLAGS += -ENTRY:DllMain
+
+NO_INSTALL_IMPORT_LIBRARY = 1
+
+endif
 else # Not Windows
 
 MODULE_OPTIMIZE_FLAGS = -O2
 ifeq ($(OS_ARCH),SunOS)
 ifndef GNU_CC
 MODULE_OPTIMIZE_FLAGS = -xO5
 endif
 endif
@@ -139,8 +156,92 @@ ifdef WRAP_MALLOC_CFLAGS
 DEFINES += -DWRAP_MALLOC
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 ifeq (Darwin,$(OS_TARGET))
 LDFLAGS += -init _jemalloc_darwin_init
 endif
+
+ifeq (WINNT,$(OS_TARGET))
+ifndef WIN32_OLD_STYLE_JEMALLOC
+
+# Roll our own custom logic here for the import library
+
+###############################################################################
+#
+# Linking Mozilla itself to jemalloc is not particularly difficult.  To do this
+# we avoid linking directly to the Microsoft-provided CRT import libraries.
+# Instead, we link to our own import library which we generate here.  To
+# replace the CRT's malloc/free/other memory management symbols we export
+# our own versions out of jemalloc.dll.  We then take the import library that
+# the compiler generates for jemalloc.dll and combine it with the MS CRT import
+# libraries.  We put our library on the command line first, and the CRT symbols
+# are discarded in favor of our versions!
+#
+# Unfortunately that was too easy.  The CRT import library is not a standard
+# import library that contains a list of symbols and whatnot.  It also includes
+# object files that are linked into generated programs.  One of these,
+# crtdll.obj is (as one might expect) linked into all DLLs that link against
+# the CRT.  This file does things like run static C++ constructors when the
+# DLL is attached, call DllMain, etc.
+#
+# In the CRT source all malloc/free calls are made to malloc_crt and free_crt.
+# In debug builds these are both defined to malloc_dbg and free_dbg.  In opt
+# builds malloc_crt is an actual function, implemented and exposed from the
+# CRT.  free_crt is, however, defined to be just plain old free.  This works
+# fine inside the CRT where malloc_crt and free operate on the same heap.
+# Outside the CRT malloc_crt is in the CRT's heap, but free is in jemalloc's
+# heap.  This causes much pain at shutdown :-(
+#
+# The obvious solution here is to override malloc_crt too.  Unfortunately,
+# that doesn't work because the CRT expects to be able to call msize on this
+# piece of memory deep inside the CRT, which will fail because it'll call the
+# CRT's msize on a pointer in jemalloc's heap.
+#
+# Our solution to this is quite devious.  We take apart the CRT's import lib
+# and remove the problematic object file.  We then poke at the object file's
+# symbol table and replace '__imp__free' (which means grab free from some
+# other DLL) with '__imp__frex'.  Then we define our own dummy no-op function
+# in jemalloc.dll and export it as frex.  Then we put the CRT import lib
+# back together with the patched crtdll.obj, glue it to the end of jemalloc's
+# import library and link the rest of Mozilla to that.
+#
+# The result?  A binary that uses jemalloc, doesn't crash, and leaks a tiny
+# amount of memory (32 words per DLL in the 2010 CRT) at shutdown.
+#
+###############################################################################
+
+libs:: $(DIST)/lib/mozcrt.lib
+
+$(DIST)/lib/mozcrt.lib:: mozcrt.lib
+	$(INSTALL) $(IFLAGS2) mozcrt.lib $(DIST)/lib
+
+# And finally combine that with the jemalloc import library to get an import
+# library that has our malloc/free/etc and the CRT's everything else
+mozcrt.lib:: $(IMPORT_LIBRARY) msvc_modified.lib
+	lib -OUT:$@ $^
+
+# Put the fixed object file back in
+msvc_modified.lib:: msvc_removed.lib crtdll_fixed.obj
+	lib -OUT:$@ $^
+
+# Fix the object file
+crtdll_fixed.obj:: crtdll.obj
+	$(PYTHON) $(srcdir)/fixcrt.py
+  
+CRTDLL_FULLPATH=$(subst \,\\,$(shell lib -list msvc_combined.lib | grep crtdll\\.obj))
+
+# Remove the broken object file, only after we have extracted it
+msvc_removed.lib:: msvc_combined.lib crtdll.obj
+	lib -OUT:$@ msvc_combined.lib -REMOVE:$(CRTDLL_FULLPATH)
+
+# Extract the broken object file out of the combined library
+crtdll.obj:: msvc_combined.lib
+	lib -OUT:$@ $^ -EXTRACT:$(CRTDLL_FULLPATH)
+
+# Grab both CRT libraries and combine them into one library to simplify things
+msvc_combined.lib::
+	lib -OUT:$@ msvcrt.lib msvcprt.lib 
+
+endif
+endif
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/fixcrt.py
@@ -0,0 +1,44 @@
+# ***** 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 build system.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Kyle Huey <me@kylehuey.com>
+#
+# 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 *****
+
+from __future__ import with_statement
+
+with open('crtdll.obj', 'rb') as infile:
+  data = infile.read()
+  with open('crtdll_fixed.obj', 'wb') as outfile:
+    data = data.replace('__imp__free', '__imp__frex')
+    outfile.write(data)
--- a/memory/jemalloc/jemalloc.c
+++ b/memory/jemalloc/jemalloc.c
@@ -201,18 +201,27 @@
 #include <stdlib.h>
 #include <limits.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 
 #ifdef MOZ_MEMORY_WINDOWS
 
+/* XXXkhuey switch to not patching the CRT for jemalloc all the time */
+/* We use ifndef NEW_STYLE here because when we're build as part of the CRT
+   we don't have access to AC_DEFINEs */
+#ifndef WIN32_NEW_STYLE_JEMALLOC
 #include <cruntime.h>
 #include <internal.h>
+#else
+/* Some defines from the CRT internal headers that we need here. */
+#define _CRT_SPINCOUNT 5000
+#define __crtInitCritSecAndSpinCount InitializeCriticalSectionAndSpinCount
+#endif
 #include <io.h>
 #include <windows.h>
 
 #pragma warning( disable: 4267 4996 4146 )
 
 #define	bool BOOL
 #define	false FALSE
 #define	true TRUE
@@ -5712,24 +5721,26 @@ malloc_shutdown()
 #if defined(MOZ_MEMORY_DARWIN)
 #define	malloc(a)	moz_malloc(a)
 #define	valloc(a)	moz_valloc(a)
 #define	calloc(a, b)	moz_calloc(a, b)
 #define	realloc(a, b)	moz_realloc(a, b)
 #define	free(a)		moz_free(a)
 #endif
 
-#if defined(MOZ_MEMORY_ANDROID) || defined(WRAP_MALLOC)
+#if defined(MOZ_MEMORY_ANDROID) || defined(WRAP_MALLOC) || defined(WIN32_NEW_STYLE_JEMALLOC)
 inline void sys_free(void* ptr) {return free(ptr);}
 #define	malloc(a)	je_malloc(a)
 #define	valloc(a)	je_valloc(a)
 #define	calloc(a, b)	je_calloc(a, b)
 #define	realloc(a, b)	je_realloc(a, b)
 #define	free(a)		je_free(a)
+#define memalign(a, b) je_memalign(a, b)
 #define posix_memalign(a, b, c)  je_posix_memalign(a, b, c)
+#define malloc_usable_size(a) je_malloc_usable_size(a)
 
 char    *je_strndup(const char *src, size_t len) {
   char* dst = (char*)je_malloc(len + 1);
   if(dst)
     strncpy(dst, src, len + 1);
   return dst;
 }
 char    *je_strdup(const char *src) {
@@ -6454,8 +6465,64 @@ void *(*__memalign_hook)(size_t alignmen
 #elif defined(RTLD_DEEPBIND)
 /*
  * XXX On systems that support RTLD_GROUP or DF_1_GROUP, do their
  * implementations permit similar inconsistencies?  Should STV_SINGLETON
  * visibility be used for interposition where available?
  */
 #  error "Interposing malloc is unsafe on this system without libc malloc hooks."
 #endif
+
+#ifdef WIN32_NEW_STYLE_JEMALLOC
+/*
+ * In the new style jemalloc integration jemalloc is built as a separate
+ * shared library.  Since we're no longer hooking into the CRT binary,
+ * we need to initialize the heap at the first opportunity we get.
+ * DLL_PROCESS_ATTACH in DllMain is that opportunity.
+ */
+BOOL APIENTRY DllMain(HINSTANCE hModule, 
+                      DWORD reason, 
+                      LPVOID lpReserved)
+{
+  switch (reason) {
+    case DLL_PROCESS_ATTACH:
+      /* Don't force the system to page DllMain back in every time
+       * we create/destroy a thread */
+      DisableThreadLibraryCalls(hModule);
+      /* Initialize the heap */
+      malloc_init_hard();
+      break;
+    
+    case DLL_PROCESS_DETACH:
+      break;
+
+  }
+
+  return TRUE;
+}
+
+/*
+ *  There's a fun allocator mismatch in (at least) the VS 2010 CRT
+ *  (see the giant comment in this directory's Makefile.in
+ *  that gets redirected here to avoid a crash on shutdown.
+ */
+void
+je_dumb_free_thunk(void *ptr)
+{
+  return; /* shutdown leaks that we don't care about */
+}
+
+#include <wchar.h>
+
+/*
+ *  We also need to provide our own impl of wcsdup so that we don't ask
+ *  the CRT for memory from its heap (which will then be unfreeable).
+ */
+wchar_t *je_wcsdup(const wchar_t *src)
+{
+  size_t len = wcslen(src);
+  wchar_t* dst = (wchar_t*)je_malloc((len + 1) * sizeof(wchar_t));
+  if(dst)
+    wcsncpy(dst, src, len + 1);
+  return dst;
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/jemalloc.def
@@ -0,0 +1,53 @@
+; ***** 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 Initial Developer of this code is the Mozilla Foundation
+;
+; Portions created by the Initial Developer are Copyright (C) 2011
+; the Initial Developer. All Rights Reserved.
+;
+; Contributor(s):
+;   Kyle Huey <me@kylehuey.com>
+;
+; Alternatively, the contents of this file may be used under the terms of
+; either of 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 *****
+
+LIBRARY jemalloc.dll
+
+EXPORTS
+  ; symbols that are actually useful
+  malloc=je_malloc
+  valloc=je_valloc
+  calloc=je_calloc
+  realloc=je_realloc
+  free=je_free
+  memalign=je_memalign
+  posix_memalign=je_posix_memalign
+  strndup=je_strndup
+  strdup=je_strdup
+  wcsdup=je_wcsdup
+  malloc_usable_size=je_malloc_usable_size
+  jemalloc_stats
+  ; A hack to work around the CRT (see giant comment in Makefile.in)
+  frex=je_dumb_free_thunk
--- a/memory/jemalloc/jemalloc.h
+++ b/memory/jemalloc/jemalloc.h
@@ -45,25 +45,27 @@ extern const char *_malloc_options;
 void	*malloc(size_t size);
 void	*valloc(size_t size);
 void	*calloc(size_t num, size_t size);
 void	*realloc(void *ptr, size_t size);
 void	free(void *ptr);
 int	posix_memalign(void **memptr, size_t alignment, size_t size);
 #endif /* MOZ_MEMORY_DARWIN, MOZ_MEMORY_LINUX */
 
-#if defined(MOZ_MEMORY_ANDROID) || defined(WRAP_MALLOC)
+#if defined(MOZ_MEMORY_ANDROID) || defined(WRAP_MALLOC) || defined(WIN32_NEW_STYLE_JEMALLOC)
 void	*je_malloc(size_t size);
 void	*je_valloc(size_t size);
 void	*je_calloc(size_t num, size_t size);
 void	*je_realloc(void *ptr, size_t size);
 void	je_free(void *ptr);
+void *je_memalign(size_t alignment, size_t size);
 int	je_posix_memalign(void **memptr, size_t alignment, size_t size);
 char    *je_strndup(const char *src, size_t len);
 char    *je_strdup(const char *src);
+size_t	je_malloc_usable_size(const void *ptr);
 #endif
 
 /* Linux has memalign and malloc_usable_size */
 #if !defined(MOZ_MEMORY_LINUX)
 void	*memalign(size_t alignment, size_t size);
 size_t	malloc_usable_size(const void *ptr);
 #endif /* MOZ_MEMORY_LINUX */
 
--- a/memory/mozalloc/mozalloc.cpp
+++ b/memory/mozalloc/mozalloc.cpp
@@ -80,17 +80,19 @@
 #include "jemalloc.h"
 #define malloc(a)     je_malloc(a)
 #define valloc(a)     je_valloc(a)
 #define calloc(a, b)  je_calloc(a, b)
 #define realloc(a, b) je_realloc(a, b)
 #define free(a)       je_free(a)
 #define strdup(a)     je_strdup(a)
 #define strndup(a, b) je_strndup(a, b)
+#define memalign(a, b) je_memalign(a, b)
 #define posix_memalign(a, b, c)  je_posix_memalign(a, b, c)
+#define malloc_usable_size(a) je_malloc_usable_size(a)
 #endif
 
 void
 moz_free(void* ptr)
 {
     free(ptr);
 }