Bug 938437 - Replace nsStaticXULComponents.cpp with smart use of sections. r=bsmedberg,irc-r=decoder,r=nfroyd
☠☠ backed out by ed4f3c12c532 ☠ ☠
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 19 Nov 2013 13:45:31 +0900
changeset 156998 1eb6ceed2cdab03108bd5de27dfab737e5093822
parent 156997 2656e9b931148c0a487742944a2fdbb32a3e5ad0
child 156999 c30371a66429ff76a0af42baaa1afa172105db84
push id25694
push usercbook@mozilla.com
push dateFri, 22 Nov 2013 13:45:11 +0000
treeherdermozilla-central@9a179f9b33ca [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, nfroyd
bugs938437
milestone28.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 938437 - Replace nsStaticXULComponents.cpp with smart use of sections. r=bsmedberg,irc-r=decoder,r=nfroyd
build/autoconf/compiler-opts.m4
config/rules.mk
js/src/build/autoconf/compiler-opts.m4
js/src/config/rules.mk
toolkit/library/Makefile.in
toolkit/library/StaticXULComponents.ld
toolkit/library/StaticXULComponentsEnd/StaticXULComponentsEnd.cpp
toolkit/library/StaticXULComponentsEnd/moz.build
toolkit/library/StaticXULComponentsStart.cpp
toolkit/library/moz.build
toolkit/library/nsStaticXULComponents.cpp
toolkit/toolkit.mozbuild
xpcom/components/Module.h
xpcom/components/nsComponentManager.cpp
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -242,16 +242,23 @@ if test "$GNU_CC" -a -n "$MOZ_FORCE_GOLD
             if $CC -B $_objdir/build/unix/gold -Wl,--version 2>&1 | grep -q "GNU gold"; then
                 LDFLAGS="$LDFLAGS -B $_objdir/build/unix/gold"
             else
                 rm -rf $_objdir/build/unix/gold
             fi
         fi
     fi
 fi
+if test "$GNU_CC"; then
+    if $CC $LDFLAGS -Wl,--version 2>&1 | grep -q "GNU ld"; then
+        LD_IS_BFD=1
+    fi
+fi
+
+AC_SUBST([LD_IS_BFD])
 
 if test "$GNU_CC"; then
     if test -z "$DEVELOPER_OPTIONS"; then
         CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
         CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
     fi
     CFLAGS="$CFLAGS -fno-math-errno"
     CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -772,16 +772,17 @@ endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 # touch it a few seconds into the future to work around FAT's
 # 2-second granularity
 	touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink
 endif
 else # !WINNT || GNU_CC
 	$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) $(STLPORT_LIBS)
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -828,16 +829,17 @@ ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		rm -f $@.manifest; \
 	fi
 endif	# MSVC with manifest tool
 else
 	$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(STLPORT_LIBS)
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -930,16 +932,17 @@ ifndef XP_MACOSX
 	dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o  $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
 endif
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
 	@$(RM) $(DTRACE_PROBE_OBJ)
 else # ! DTRACE_LIB_DEPENDENT
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
 endif # DTRACE_LIB_DEPENDENT
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 		rm -f $@.manifest; \
 	fi
--- a/js/src/build/autoconf/compiler-opts.m4
+++ b/js/src/build/autoconf/compiler-opts.m4
@@ -242,16 +242,23 @@ if test "$GNU_CC" -a -n "$MOZ_FORCE_GOLD
             if $CC -B $_objdir/build/unix/gold -Wl,--version 2>&1 | grep -q "GNU gold"; then
                 LDFLAGS="$LDFLAGS -B $_objdir/build/unix/gold"
             else
                 rm -rf $_objdir/build/unix/gold
             fi
         fi
     fi
 fi
+if test "$GNU_CC"; then
+    if $CC $LDFLAGS -Wl,--version 2>&1 | grep -q "GNU ld"; then
+        LD_IS_BFD=1
+    fi
+fi
+
+AC_SUBST([LD_IS_BFD])
 
 if test "$GNU_CC"; then
     if test -z "$DEVELOPER_OPTIONS"; then
         CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
         CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
     fi
     CFLAGS="$CFLAGS -fno-math-errno"
     CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -772,16 +772,17 @@ endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 # touch it a few seconds into the future to work around FAT's
 # 2-second granularity
 	touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink
 endif
 else # !WINNT || GNU_CC
 	$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) $(STLPORT_LIBS)
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -828,16 +829,17 @@ ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		rm -f $@.manifest; \
 	fi
 endif	# MSVC with manifest tool
 else
 	$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(STLPORT_LIBS)
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -930,16 +932,17 @@ ifndef XP_MACOSX
 	dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o  $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
 endif
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
 	@$(RM) $(DTRACE_PROBE_OBJ)
 else # ! DTRACE_LIB_DEPENDENT
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
 endif # DTRACE_LIB_DEPENDENT
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 		rm -f $@.manifest; \
 	fi
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -64,59 +64,16 @@ symverscript: symverscript.in
 	$(call py_action,preprocessor, \
 		-DVERSION="$(LIBRARY_NAME)$(MOZILLA_SYMBOLVERSION)" $< -o $@)
 
 EXTRA_DEPS += symverscript
 endif
 endif
 
 # component libraries
-ifdef MOZ_JSDEBUGGER
-DEFINES += -DMOZ_JSDEBUGGER
-endif
-
-ifdef MOZ_PREF_EXTENSIONS
-DEFINES += -DMOZ_PREF_EXTENSIONS
-endif
-
-ifdef MOZ_AUTH_EXTENSION
-DEFINES += -DMOZ_AUTH_EXTENSION
-endif
-
-ifdef MOZ_PERMISSIONS
-DEFINES += -DMOZ_PERMISSIONS
-endif
-
-ifdef MOZ_UNIVERSALCHARDET
-DEFINES += -DMOZ_UNIVERSALCHARDET
-endif
-
-ifeq (,$(filter android gonk qt os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
-ifdef MOZ_XUL
-DEFINES += -DMOZ_FILEVIEW
-endif
-endif
-
-# Platform-specific icon channel stuff - supported mostly-everywhere
-ifneq (,$(filter windows os2 mac cocoa gtk2 gtk3 qt android,$(MOZ_WIDGET_TOOLKIT)))
-DEFINES += -DICON_DECODER
-endif
-
-ifdef MOZ_SPELLCHECK
-DEFINES += -DMOZ_SPELLCHECK
-endif
-
-ifdef MOZ_ZIPWRITER
-DEFINES += -DMOZ_ZIPWRITER
-endif
-
-ifdef MOZ_GIO_COMPONENT
-DEFINES += -DMOZ_GIO_COMPONENT
-endif
-
 ifdef MOZ_APP_COMPONENT_LIBS
 COMPONENT_LIBS += $(MOZ_APP_COMPONENT_LIBS)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 OS_LIBS += -framework OpenGL -lcups
 endif
 
@@ -395,22 +352,16 @@ OS_LIBS += $(LIBICONV)
 DEFINES += \
   -DIMPL_LIBXUL \
   $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 OS_LIBS += $(call EXPAND_LIBNAME,usp10 oleaut32)
 endif
 
-ifdef MOZ_DEBUG
-ifdef ENABLE_TESTS
-DEFINES += -DENABLE_LAYOUTDEBUG
-endif
-endif
-
 ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_PROFILE_USE))
 # Wrap linker to measure peak virtual memory usage.
 LD := $(PYTHON) $(topsrcdir)/build/link.py $(CURDIR)/linker-vsize $(LD)
 endif
 
 ifndef LINK_GTEST
 ifdef COMPILE_ENVIRONMENT
 libs:: $(FINAL_TARGET)/dependentlibs.list
@@ -439,8 +390,37 @@ COMPONENT_LIBS += \
   gtest \
   gfxtest \
   ssltest \
   $(NULL)
 endif
 
 $(FINAL_TARGET)/dependentlibs.list: dependentlibs.py $(SHARED_LIBRARY) $(wildcard $(if $(wildcard $(FINAL_TARGET)/dependentlibs.list),$(addprefix $(FINAL_TARGET)/,$(shell cat $(FINAL_TARGET)/dependentlibs.list))))
 	$(PYTHON) $< $(SHARED_LIBRARY) -L $(FINAL_TARGET) $(if $(TOOLCHAIN_PREFIX),$(addprefix -p ,$(TOOLCHAIN_PREFIX))) > $@
+
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME_PATH,StaticXULComponentsEnd,$(CURDIR)/StaticXULComponentsEnd)
+
+# BFD ld doesn't create multiple PT_LOADs as usual when an unknown section
+# exists. Using an implicit linker script to make it fold that section in
+# .data.rel.ro makes it create multiple PT_LOADs. That implicit linker
+# script however makes gold misbehave, first because it doesn't like that
+# the linker script is given after crtbegin.o, and even past that, replaces
+# the default section rules with those from the script instead of
+# supplementing them. Which leads to a lib with a huge load of sections.
+ifdef LD_IS_BFD
+EXTRA_DSO_LDOPTS += $(srcdir)/StaticXULComponents.ld
+endif
+
+# This, combined with the fact the file is first, makes the start pointer
+# first in Windows PGO builds.
+NO_PROFILE_GUIDED_OPTIMIZE = StaticXULComponentsStart.cpp
+
+ifeq (WINNT,$(OS_TARGET))
+get_first_and_last = dumpbin -exports $1 | grep _NSModule@@ | sort -k 3 | sed -n 's/^.*?\([^@]*\)@@.*$$/\1/;1p;$$p'
+else
+get_first_and_last = $(TOOLCHAIN_PREFIX)nm -g $1 | grep _NSModule$$ | sort | sed -n 's/^.* _*\([^ ]*\)$$/\1/;1p;$$p'
+endif
+
+LOCAL_CHECKS = test "$$($(get_first_and_last) | xargs echo)" != "start_kPStaticModules_NSModule end_kPStaticModules_NSModule" && echo "NSModules are not ordered appropriately" && exit 1 || exit 0
+
+ifeq (Linux,$(OS_ARCH))
+LOCAL_CHECKS += ; test "$$($(TOOLCHAIN_PREFIX)readelf -l $1 | awk '$1 == "LOAD" { t += 1 } END { print t }')" -le 1 && echo "Only one PT_LOAD segment" && exit 1 || exit 0
+endif
new file mode 100644
--- /dev/null
+++ b/toolkit/library/StaticXULComponents.ld
@@ -0,0 +1,5 @@
+SECTIONS {
+  .data.rel.ro : {
+    *(.kPStaticModules)
+  }
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/library/StaticXULComponentsEnd/StaticXULComponentsEnd.cpp
@@ -0,0 +1,14 @@
+#include "mozilla/Module.h"
+#include "mozilla/NullPtr.h"
+
+/* Ensure end_kPStaticModules is at the end of the .kPStaticModules section
+ * on Windows. Somehow, placing the object last is not enough with PGO/LTCG. */
+#ifdef _MSC_VER
+/* Sections on Windows are in two parts, separated with $. When linking,
+ * sections with the same first part are all grouped, and ordered
+ * alphabetically with the second part as sort key. */
+#  pragma section(".kPStaticModules$Z", read)
+#  undef NSMODULE_SECTION
+#  define NSMODULE_SECTION __declspec(allocate(".kPStaticModules$Z"), dllexport)
+#endif
+NSMODULE_DEFN(end_kPStaticModules) = nullptr;
new file mode 100644
--- /dev/null
+++ b/toolkit/library/StaticXULComponentsEnd/moz.build
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SOURCES += [
+    'StaticXULComponentsEnd.cpp',
+]
+
+LIBRARY_NAME = 'StaticXULComponentsEnd'
+
+LIBXUL_LIBRARY = True
new file mode 100644
--- /dev/null
+++ b/toolkit/library/StaticXULComponentsStart.cpp
@@ -0,0 +1,4 @@
+#include "mozilla/Module.h"
+#include "mozilla/NullPtr.h"
+
+NSMODULE_DEFN(start_kPStaticModules) = nullptr;
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -5,17 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['MOZ_METRO'] and CONFIG['OS_ARCH'] == 'WINNT':
     DIRS += ['winvccorlib']
 
 LIBRARY_NAME = 'xul'
 
 SOURCES += [
-    'nsStaticXULComponents.cpp',
+    'StaticXULComponentsStart.cpp',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     SOURCES += [
         'nsDllMain.cpp',
     ]
 
 MSVC_ENABLE_PGO = True
deleted file mode 100644
--- a/toolkit/library/nsStaticXULComponents.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/Module.h"
-#include "nsXPCOM.h"
-#include "nsMemory.h"
-
-#ifdef MOZ_AUTH_EXTENSION
-#define AUTH_MODULE    MODULE(nsAuthModule)
-#else
-#define AUTH_MODULE
-#endif
-
-#ifdef MOZ_PERMISSIONS
-#define PERMISSIONS_MODULES                  \
-    MODULE(nsCookieModule)                   \
-    MODULE(nsPermissionsModule)
-#else
-#define PERMISSIONS_MODULES
-#endif
-
-#ifdef MOZ_UNIVERSALCHARDET
-#define UNIVERSALCHARDET_MODULE MODULE(nsUniversalCharDetModule)
-#else
-#define UNIVERSALCHARDET_MODULE
-#endif
-
-#ifdef XP_WIN
-#  define WIDGET_MODULES MODULE(nsWidgetModule)
-#elif defined(XP_MACOSX)
-#  define WIDGET_MODULES MODULE(nsWidgetMacModule)
-#elif defined(XP_OS2)
-#  define WIDGET_MODULES MODULE(nsWidgetOS2Module)
-#elif defined(MOZ_WIDGET_GTK)
-#  define WIDGET_MODULES MODULE(nsWidgetGtk2Module)
-#elif defined(MOZ_WIDGET_QT)
-#  define WIDGET_MODULES MODULE(nsWidgetQtModule)
-#elif defined(MOZ_WIDGET_ANDROID)
-#  define WIDGET_MODULES MODULE(nsWidgetAndroidModule)
-#elif defined(MOZ_WIDGET_GONK)
-#  define WIDGET_MODULES MODULE(nsWidgetGonkModule)
-#else
-#  error Unknown widget module.
-#endif
-
-#ifdef ICON_DECODER
-#define ICON_MODULE MODULE(nsIconDecoderModule)
-#else
-#define ICON_MODULE
-#endif
-
-#ifdef MOZ_ENABLE_XREMOTE
-#define XREMOTE_MODULES MODULE(RemoteServiceModule)
-#else
-#define XREMOTE_MODULES
-#endif
-
-#ifdef MOZ_PREF_EXTENSIONS
-#define SYSTEMPREF_MODULES MODULE(nsAutoConfigModule)
-#else
-#define SYSTEMPREF_MODULES
-#endif
-
-#ifdef ENABLE_LAYOUTDEBUG
-#define LAYOUT_DEBUG_MODULE MODULE(nsLayoutDebugModule)
-#else
-#define LAYOUT_DEBUG_MODULE
-#endif
-
-#ifdef MOZ_JSDEBUGGER
-#define JSDEBUGGER_MODULES \
-    MODULE(JavaScript_Debugger)
-#else
-#define JSDEBUGGER_MODULES
-#endif
-
-#if defined(MOZ_FILEVIEW) && defined(MOZ_XUL)
-#define FILEVIEW_MODULE MODULE(nsFileViewModule)
-#else
-#define FILEVIEW_MODULE
-#endif
-
-#ifdef MOZ_ZIPWRITER
-#define ZIPWRITER_MODULE MODULE(ZipWriterModule)
-#else
-#define ZIPWRITER_MODULE
-#endif
-
-#ifdef MOZ_PLACES
-#define PLACES_MODULES \
-    MODULE(nsPlacesModule)
-#else
-#define PLACES_MODULES
-#endif
-
-#ifdef MOZ_XUL
-#define XULENABLED_MODULES                   \
-    MODULE(tkAutoCompleteModule)             \
-    MODULE(satchel)                          \
-    MODULE(PKI)
-#else
-#define XULENABLED_MODULES
-#endif
-
-#ifdef MOZ_SPELLCHECK
-#define SPELLCHECK_MODULE MODULE(mozSpellCheckerModule)
-#else
-#define SPELLCHECK_MODULE
-#endif
-
-#ifdef MOZ_XUL
-#ifdef MOZ_WIDGET_GTK
-#define UNIXPROXY_MODULE MODULE(nsUnixProxyModule)
-#endif
-#if defined(MOZ_WIDGET_QT)
-#define UNIXPROXY_MODULE MODULE(nsUnixProxyModule)
-#endif
-#endif
-#ifndef UNIXPROXY_MODULE
-#define UNIXPROXY_MODULE
-#endif
-
-#if defined(XP_MACOSX)
-#define OSXPROXY_MODULE MODULE(nsOSXProxyModule)
-#else
-#define OSXPROXY_MODULE
-#endif
-
-#if defined(XP_WIN)
-#define WINDOWSPROXY_MODULE MODULE(nsWindowsProxyModule)
-#else
-#define WINDOWSPROXY_MODULE
-#endif
-
-#if defined(MOZ_WIDGET_ANDROID)
-#define ANDROIDPROXY_MODULE MODULE(nsAndroidProxyModule)
-#else
-#define ANDROIDPROXY_MODULE
-#endif
-
-#if defined(BUILD_CTYPES)
-#define JSCTYPES_MODULE MODULE(jsctypes)
-#else
-#define JSCTYPES_MODULE
-#endif
-
-#ifndef MOZ_APP_COMPONENT_MODULES
-#if defined(MOZ_APP_COMPONENT_INCLUDE)
-#include MOZ_APP_COMPONENT_INCLUDE
-#define MOZ_APP_COMPONENT_MODULES APP_COMPONENT_MODULES
-#else
-#define MOZ_APP_COMPONENT_MODULES
-#endif
-#endif
-
-#if defined(MOZ_ENABLE_PROFILER_SPS)
-#define PROFILER_MODULE MODULE(nsProfilerModule)
-#else
-#define PROFILER_MODULE
-#endif
-
-#if defined(MOZ_WEBRTC)
-#define PEERCONNECTION_MODULE MODULE(peerconnection)
-#else
-#define PEERCONNECTION_MODULE
-#endif
-
-#if defined(MOZ_GIO_COMPONENT)
-#define GIO_MODULE MODULE(nsGIOModule)
-#else
-#define GIO_MODULE
-#endif
-
-#if defined(MOZ_SYNTH_PICO)
-#define SYNTH_PICO_MODULE MODULE(synthpico)
-#else
-#define SYNTH_PICO_MODULE
-#endif
-
-#define XUL_MODULES                          \
-    MODULE(nsUConvModule)                    \
-    MODULE(nsI18nModule)                     \
-    MODULE(nsChardetModule)                  \
-    UNIVERSALCHARDET_MODULE                  \
-    MODULE(necko)                            \
-    PERMISSIONS_MODULES                      \
-    AUTH_MODULE                              \
-    MODULE(nsJarModule)                      \
-    ZIPWRITER_MODULE                         \
-    MODULE(StartupCacheModule)               \
-    MODULE(nsPrefModule)                     \
-    MODULE(nsRDFModule)                      \
-    MODULE(nsWindowDataSourceModule)         \
-    MODULE(nsParserModule)                   \
-    MODULE(nsImageLib2Module)                \
-    MODULE(nsMediaSnifferModule)             \
-    MODULE(nsGfxModule)                      \
-    PROFILER_MODULE                          \
-    WIDGET_MODULES                           \
-    ICON_MODULE                              \
-    MODULE(nsPluginModule)                   \
-    MODULE(nsLayoutModule)                   \
-    MODULE(docshell_provider)                \
-    MODULE(embedcomponents)                  \
-    MODULE(Browser_Embedding_Module)         \
-    MODULE(appshell)                         \
-    MODULE(nsTransactionManagerModule)       \
-    MODULE(nsComposerModule)                 \
-    MODULE(application)                      \
-    MODULE(Apprunner)                        \
-    MODULE(CommandLineModule)                \
-    FILEVIEW_MODULE                          \
-    MODULE(mozStorageModule)                 \
-    PLACES_MODULES                           \
-    XULENABLED_MODULES                       \
-    MODULE(nsToolkitCompsModule)             \
-    XREMOTE_MODULES                          \
-    JSDEBUGGER_MODULES                       \
-    MODULE(BOOT)                             \
-    MODULE(NSS)                              \
-    SYSTEMPREF_MODULES                       \
-    SPELLCHECK_MODULE                        \
-    LAYOUT_DEBUG_MODULE                      \
-    UNIXPROXY_MODULE                         \
-    OSXPROXY_MODULE                          \
-    WINDOWSPROXY_MODULE                      \
-    ANDROIDPROXY_MODULE                      \
-    JSCTYPES_MODULE                          \
-    MODULE(jsreflect)                        \
-    MODULE(jsperf)                           \
-    MODULE(identity)                         \
-    MODULE(nsServicesCryptoModule)           \
-    MOZ_APP_COMPONENT_MODULES                \
-    MODULE(nsTelemetryModule)                \
-    MODULE(jsinspector)                      \
-    MODULE(jsdebugger)                       \
-    PEERCONNECTION_MODULE                    \
-    GIO_MODULE                               \
-    SYNTH_PICO_MODULE                        \
-    MODULE(DiskSpaceWatcherModule)           \
-    /* end of list */
-
-#define MODULE(_name) \
-  NSMODULE_DECL(_name);
-
-XUL_MODULES
-
-#ifdef MOZ_WIDGET_GONK
-MODULE(WifiProxyServiceModule)
-#endif
-
-#undef MODULE
-
-#define MODULE(_name) \
-    &NSMODULE_NAME(_name),
-
-extern const mozilla::Module *const *const kPStaticModules[] = {
-  XUL_MODULES
-#ifdef MOZ_WIDGET_GONK
-MODULE(WifiProxyServiceModule)
-#endif
-  nullptr
-};
-
-#undef MODULE
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -156,16 +156,17 @@ add_tier_dir('platform', 'other-licenses
 if CONFIG['MOZ_GIO_COMPONENT']:
     add_tier_dir('platform', 'extensions/gio')
 
 # Applications can cheat and ask for code to be
 # built before libxul so it can be linked into libxul.
 add_tier_dir('platform', app_libxul_dirs)
 add_tier_dir('platform', app_libxul_static_dirs, static=True)
 
+add_tier_dir('platform', 'toolkit/library/StaticXULComponentsEnd')
 add_tier_dir('platform', 'toolkit/library')
 
 if CONFIG['MOZ_REPLACE_MALLOC']:
     add_tier_dir('platform', 'memory/replace')
 
 if CONFIG['NS_TRACE_MALLOC']:
     add_tier_dir('platform', 'tools/trace-malloc')
 
--- a/xpcom/components/Module.h
+++ b/xpcom/components/Module.h
@@ -100,16 +100,29 @@ struct Module
   LoadFuncPtr loadProc;
   UnloadFuncPtr unloadProc;
 };
 
 } // namespace
 
 #if defined(MOZILLA_INTERNAL_API)
 #  define NSMODULE_NAME(_name) _name##_NSModule
-#  define NSMODULE_DECL(_name) extern mozilla::Module const *const NSMODULE_NAME(_name)
-#  define NSMODULE_DEFN(_name) NSMODULE_DECL(_name)
+#  if defined(_MSC_VER)
+#    pragma section(".kPStaticModules$M", read)
+#    pragma comment(linker, "/merge:.kPStaticModules=.rdata")
+#    define NSMODULE_SECTION __declspec(allocate(".kPStaticModules$M"), dllexport)
+#  elif defined(__GNUC__)
+#    if defined(__ELF__)
+#      define NSMODULE_SECTION __attribute__((section(".kPStaticModules"), visibility("protected")))
+#    elif defined(__MACH__)
+#      define NSMODULE_SECTION __attribute__((section("__DATA, .kPStaticModules"), visibility("default")))
+#    endif
+#  endif
+#  if !defined(NSMODULE_SECTION)
+#    error Do not know how to define sections.
+#  endif
+#  define NSMODULE_DEFN(_name) extern NSMODULE_SECTION mozilla::Module const *const NSMODULE_NAME(_name)
 #else
 #  define NSMODULE_NAME(_name) NSModule
 #  define NSMODULE_DEFN(_name) extern "C" NS_EXPORT mozilla::Module const *const NSModule
 #endif
 
 #endif // mozilla_Module_h
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -77,20 +77,16 @@
 #include "mozilla/Omnijar.h"
 
 #include "prlog.h"
 
 using namespace mozilla;
 
 PRLogModuleInfo* nsComponentManagerLog = nullptr;
 
-// defined in nsStaticXULComponents.cpp to contain all the components in
-// libxul.
-extern mozilla::Module const *const *const kPStaticModules[];
-
 #if 0 || defined (DEBUG_timeless)
  #define SHOW_DENIED_ON_SHUTDOWN
  #define SHOW_CI_ON_EXISTING_SERVICE
 #endif
 
 // Bloated registry buffer size to improve startup performance -- needs to
 // be big enough to fit the entire file into memory or it'll thrash.
 // 512K is big enough to allow for some future growth in the registry.
@@ -320,26 +316,36 @@ nsComponentManagerImpl::nsComponentManag
     , mContractIDs(CONTRACTID_HASHTABLE_INITIAL_SIZE)
     , mLock("nsComponentManagerImpl.mLock")
     , mStatus(NOT_INITIALIZED)
 {
 }
 
 nsTArray<const mozilla::Module*>* nsComponentManagerImpl::sStaticModules;
 
+NSMODULE_DEFN(start_kPStaticModules);
+NSMODULE_DEFN(end_kPStaticModules);
+
+/* The content between start_kPStaticModules and end_kPStaticModules is gathered
+ * by the linker from various objects containing symbols in a specific section.
+ * ASAN considers (rightfully) the use of this content as a global buffer
+ * overflow. But this is a deliberate and well-considered choice, with no proper
+ * way to make ASAN happy. */
+MOZ_ASAN_BLACKLIST
 /* static */ void
 nsComponentManagerImpl::InitializeStaticModules()
 {
     if (sStaticModules)
         return;
 
     sStaticModules = new nsTArray<const mozilla::Module*>;
-    for (const mozilla::Module *const *const *staticModules = kPStaticModules;
-         *staticModules; ++staticModules)
-        sStaticModules->AppendElement(**staticModules);
+    for (const mozilla::Module *const *staticModules = &NSMODULE_NAME(start_kPStaticModules) + 1;
+         staticModules < &NSMODULE_NAME(end_kPStaticModules); ++staticModules)
+        if (*staticModules) // ASAN adds padding
+            sStaticModules->AppendElement(*staticModules);
 }
 
 nsTArray<nsComponentManagerImpl::ComponentLocation>*
 nsComponentManagerImpl::sModuleLocations;
 
 /* static */ void
 nsComponentManagerImpl::InitializeModuleLocations()
 {