Bug 1420355 - Statically link DMD. r=njn
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 28 Nov 2017 08:10:48 +0900
changeset 394040 eff8b66ce5c777b9084b74f416c6e7400a0ed430
parent 394039 076e21f3b25ec4598f64208d02cbbc9104d99949
child 394041 8316864557a24cb7c50ff18a6cd7d0939e87bf31
push id32989
push userdluca@mozilla.com
push dateWed, 29 Nov 2017 10:09:52 +0000
treeherdermozilla-central@40b464eb6b31 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1420355
milestone59.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 1420355 - Statically link DMD. r=njn
browser/installer/package-manifest.in
build/automation.py.in
build/mobile/remoteautomation.py
memory/build/mozjemalloc.cpp
memory/replace/dmd/moz.build
memory/replace/dmd/test/test_dmd.js
memory/replace/logalloc/replay/moz.build
python/mozbuild/mozbuild/mach_commands.py
testing/awsy/mach_commands.py
testing/mochitest/mochitest_options.py
testing/mochitest/runtests.py
testing/mochitest/runtestsremote.py
testing/mozbase/mozrunner/mozrunner/utils.py
testing/xpcshell/runxpcshelltests.py
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -63,19 +63,16 @@
 [xpcom]
 @RESPATH@/dependentlibs.list
 #ifdef MOZ_SHARED_MOZGLUE
 @BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
 #endif
 #ifndef MOZ_STATIC_JS
 @BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
 #endif
-#ifdef MOZ_DMD
-@BINPATH@/@DLL_PREFIX@dmd@DLL_SUFFIX@
-#endif
 #ifndef MOZ_SYSTEM_NSPR
 #ifndef MOZ_FOLD_LIBS
 @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@plc4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
 #endif
 #endif
 #ifdef XP_MACOSX
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -178,43 +178,32 @@ class Automation(object):
     def kill(self):
       if Automation().IS_WIN32:
         import platform
         pid = "%i" % self.pid
         subprocess.Popen(["taskkill", "/F", "/PID", pid]).wait()
       else:
         os.kill(self.pid, signal.SIGKILL)
 
-  def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, dmdPath=None, lsanPath=None, ubsanPath=None):
+  def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, lsanPath=None, ubsanPath=None):
     if xrePath == None:
       xrePath = self.DIST_BIN
     if env == None:
       env = dict(os.environ)
 
     ldLibraryPath = os.path.abspath(os.path.join(SCRIPT_DIR, xrePath))
-    dmdLibrary = None
-    preloadEnvVar = None
     if self.UNIXISH or self.IS_MAC:
       envVar = "LD_LIBRARY_PATH"
-      preloadEnvVar = "LD_PRELOAD"
       if self.IS_MAC:
         envVar = "DYLD_LIBRARY_PATH"
-        dmdLibrary = "libdmd.dylib"
-      else: # unixish
-        dmdLibrary = "libdmd.so"
       if envVar in env:
         ldLibraryPath = ldLibraryPath + ":" + env[envVar]
       env[envVar] = ldLibraryPath
     elif self.IS_WIN32:
       env["PATH"] = env["PATH"] + ";" + str(ldLibraryPath)
-      dmdLibrary = "dmd.dll"
-      preloadEnvVar = "MOZ_REPLACE_MALLOC_LIB"
-
-    if dmdPath and dmdLibrary and preloadEnvVar:
-      env[preloadEnvVar] = os.path.join(dmdPath, dmdLibrary)
 
     if crashreporter and not debugger:
       env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
       env['MOZ_CRASHREPORTER'] = '1'
     else:
       env['MOZ_CRASHREPORTER_DISABLE'] = '1'
 
     # Crash on non-local network connections by default.
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -55,25 +55,22 @@ class RemoteAutomation(Automation):
 
     def setProduct(self, product):
         self._product = product
 
     def setRemoteLog(self, logfile):
         self._remoteLog = logfile
 
     # Set up what we need for the remote environment
-    def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, dmdPath=None, lsanPath=None, ubsanPath=None):
+    def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, lsanPath=None, ubsanPath=None):
         # Because we are running remote, we don't want to mimic the local env
         # so no copying of os.environ
         if env is None:
             env = {}
 
-        if dmdPath:
-            env['MOZ_REPLACE_MALLOC_LIB'] = os.path.join(dmdPath, 'libdmd.so')
-
         # Except for the mochitest results table hiding option, which isn't
         # passed to runtestsremote.py as an actual option, but through the
         # MOZ_HIDE_RESULTS_TABLE environment variable.
         if 'MOZ_HIDE_RESULTS_TABLE' in os.environ:
             env['MOZ_HIDE_RESULTS_TABLE'] = os.environ['MOZ_HIDE_RESULTS_TABLE']
 
         if crashreporter and not debugger:
             env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
--- a/memory/build/mozjemalloc.cpp
+++ b/memory/build/mozjemalloc.cpp
@@ -4872,16 +4872,19 @@ replace_malloc_handle()
 #endif
 
 static void
 replace_malloc_init_funcs();
 
 #ifdef MOZ_REPLACE_MALLOC_STATIC
 extern "C" void
 logalloc_init(malloc_table_t*, ReplaceMallocBridge**);
+
+extern "C" void
+dmd_init(malloc_table_t*, ReplaceMallocBridge**);
 #endif
 
 bool
 Equals(malloc_table_t& aTable1, malloc_table_t& aTable2)
 {
   return memcmp(&aTable1, &aTable2, sizeof(malloc_table_t)) == 0;
 }
 
@@ -4908,16 +4911,21 @@ init()
   gReplaceMallocInitialized = true;
   if (replace_init) {
     replace_init(&gReplaceMallocTable, &gReplaceMallocBridge);
   }
 #ifdef MOZ_REPLACE_MALLOC_STATIC
   if (Equals(initialTable, gReplaceMallocTable)) {
     logalloc_init(&gReplaceMallocTable, &gReplaceMallocBridge);
   }
+#ifdef MOZ_DMD
+  if (Equals(initialTable, gReplaceMallocTable)) {
+    dmd_init(&gReplaceMallocTable, &gReplaceMallocBridge);
+  }
+#endif
 #endif
   replace_malloc_init_funcs();
 }
 
 #define MALLOC_DECL(name, return_type, ...)                                    \
   template<>                                                                   \
   inline return_type ReplaceMalloc::name(                                      \
     ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__))                                    \
--- a/memory/replace/dmd/moz.build
+++ b/memory/replace/dmd/moz.build
@@ -4,24 +4,28 @@
 # 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/.
 
 EXPORTS += [
     'DMD.h',
 ]
 
 UNIFIED_SOURCES += [
-    '../../../mfbt/HashFunctions.cpp',
-    '../../../mfbt/JSONWriter.cpp',
-    '../../../mfbt/Poison.cpp',
-    '../../../mozglue/misc/StackWalk.cpp',
     'DMD.cpp',
 ]
 
-SharedLibrary('dmd')
+if not CONFIG['MOZ_REPLACE_MALLOC_STATIC']:
+    UNIFIED_SOURCES += [
+        '/mfbt/HashFunctions.cpp',
+        '/mfbt/JSONWriter.cpp',
+        '/mfbt/Poison.cpp',
+        '/mozglue/misc/StackWalk.cpp',
+    ]
+
+ReplaceMalloc('dmd')
 
 DEFINES['MOZ_NO_MOZALLOC'] = True
 DEFINES['IMPL_MFBT'] = True
 DEFINES['XPCOM_GLUE'] = True
 
 if CONFIG['MOZ_OPTIMIZE']:
     DEFINES['MOZ_OPTIMIZE'] = True
 
--- a/memory/replace/dmd/test/test_dmd.js
+++ b/memory/replace/dmd/test/test_dmd.js
@@ -132,17 +132,16 @@ function run_test() {
   // that generates the JSON output, and the script that post-processes that
   // output.
   //
   // Run these synchronously, because test() updates the complete*.json files
   // in-place (to fix stacks) when it runs dmd.py, and that's not safe to do
   // asynchronously.
 
   gEnv.set('DMD', '1');
-  gEnv.set(gEnv.get("DMD_PRELOAD_VAR"), gEnv.get("DMD_PRELOAD_VALUE"));
 
   runProcess(gDmdTestFile, []);
 
   function test2(aTestName, aMode) {
     let name = "complete-" + aTestName + "-" + aMode;
     jsonFile = FileUtils.getFile("CurWorkD", [name + ".json"]);
     test(name, [jsonFile.path]);
     jsonFile.remove(true);
--- a/memory/replace/logalloc/replay/moz.build
+++ b/memory/replace/logalloc/replay/moz.build
@@ -7,16 +7,24 @@
 Program('logalloc-replay')
 
 SOURCES += [
     '/mfbt/Assertions.cpp',
     '/mfbt/Unused.cpp',
     'Replay.cpp',
 ]
 
+if CONFIG['MOZ_REPLACE_MALLOC_STATIC'] and CONFIG['MOZ_DMD']:
+    UNIFIED_SOURCES += [
+        '/mfbt/HashFunctions.cpp',
+        '/mfbt/JSONWriter.cpp',
+        '/mfbt/Poison.cpp',
+        '/mozglue/misc/StackWalk.cpp',
+    ]
+
 if not CONFIG['MOZ_REPLACE_MALLOC_STATIC']:
     SOURCES += [
         '../FdPrintf.cpp',
     ]
 
 LOCAL_INCLUDES += [
     '..',
 ]
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -915,45 +915,20 @@ class RunProgram(MachCommandBase):
 
             if mode:
                 dmd_params.append('--mode=' + mode)
             if stacks:
                 dmd_params.append('--stacks=' + stacks)
             if show_dump_stats:
                 dmd_params.append('--show-dump-stats=yes')
 
-            bin_dir = os.path.dirname(binpath)
-            lib_name = self.substs['DLL_PREFIX'] + 'dmd' + self.substs['DLL_SUFFIX']
-            dmd_lib = os.path.join(bin_dir, lib_name)
-            if not os.path.exists(dmd_lib):
-                print("Please build with |--enable-dmd| to use DMD.")
-                return 1
-
-            env_vars = {
-                "Darwin": {
-                    "DYLD_INSERT_LIBRARIES": dmd_lib,
-                    "LD_LIBRARY_PATH": bin_dir,
-                },
-                "Linux": {
-                    "LD_PRELOAD": dmd_lib,
-                    "LD_LIBRARY_PATH": bin_dir,
-                },
-                "WINNT": {
-                    "MOZ_REPLACE_MALLOC_LIB": dmd_lib,
-                },
-            }
-
-            arch = self.substs['OS_ARCH']
-
             if dmd_params:
-                env_vars[arch]["DMD"] = " ".join(dmd_params)
+                extra_env['DMD'] = ' '.join(dmd_params)
             else:
-                env_vars[arch]["DMD"] = "1"
-
-            extra_env.update(env_vars.get(arch, {}))
+                extra_env['DMD'] = '1'
 
         return self.run_process(args=args, ensure_exit_code=False,
             pass_thru=True, append_env=extra_env)
 
 @CommandProvider
 class Buildsymbols(MachCommandBase):
     """Produce a package of debug symbols suitable for use with Breakpad."""
 
--- a/testing/awsy/mach_commands.py
+++ b/testing/awsy/mach_commands.py
@@ -139,42 +139,18 @@ class MachCommands(MachCommandBase):
             self.run_process(**unzip_args)
 
         # If '--preferences' was not specified supply our default set.
         if not kwargs['prefs_files']:
             kwargs['prefs_files'] = [os.path.join(awsy_source_dir, 'conf', 'prefs.json')]
 
         # Setup DMD env vars if necessary.
         if kwargs['dmd']:
-            dmd_params = []
-
             bin_dir = os.path.dirname(binary)
-            lib_name = self.substs['DLL_PREFIX'] + 'dmd' + self.substs['DLL_SUFFIX']
-            dmd_lib = os.path.join(bin_dir, lib_name)
-            if not os.path.exists(dmd_lib):
-                print("Please build with |--enable-dmd| to use DMD.")
-                return 1
 
-            env_vars = {
-                "Darwin": {
-                    "DYLD_INSERT_LIBRARIES": dmd_lib,
-                    "LD_LIBRARY_PATH": bin_dir,
-                },
-                "Linux": {
-                    "LD_PRELOAD": dmd_lib,
-                    "LD_LIBRARY_PATH": bin_dir,
-                },
-                "WINNT": {
-                    "MOZ_REPLACE_MALLOC_LIB": dmd_lib,
-                },
-            }
-
-            arch = self.substs['OS_ARCH']
-            for k, v in env_vars[arch].iteritems():
-                os.environ[k] = v
             if 'DMD' not in os.environ:
                 os.environ['DMD'] = '1'
 
             # Also add the bin dir to the python path so we can use dmd.py
             if bin_dir not in sys.path:
                 sys.path.append(bin_dir)
 
         for k, v in kwargs.iteritems():
--- a/testing/mochitest/mochitest_options.py
+++ b/testing/mochitest/mochitest_options.py
@@ -429,22 +429,16 @@ class MochitestArguments(ArgumentContain
           "default": False,
           "help": "Run tests with nested_oop preferences and test filtering enabled.",
           }],
         [["--dmd"],
          {"action": "store_true",
           "default": False,
           "help": "Run tests with DMD active.",
           }],
-        [["--dmd-path"],
-         {"default": None,
-          "dest": "dmdPath",
-          "help": "Specifies the path to the directory containing the shared library for DMD.",
-          "suppress": True,
-          }],
         [["--dump-output-directory"],
          {"default": None,
           "dest": "dumpOutputDirectory",
           "help": "Specifies the directory in which to place dumped memory reports.",
           }],
         [["--dump-about-memory-after-test"],
          {"action": "store_true",
           "default": False,
@@ -696,26 +690,16 @@ class MochitestArguments(ArgumentContain
 
         # allow relative paths
         if options.xrePath:
             options.xrePath = self.get_full_path(options.xrePath, parser.oldcwd)
 
         if options.profilePath:
             options.profilePath = self.get_full_path(options.profilePath, parser.oldcwd)
 
-        if options.dmdPath:
-            options.dmdPath = self.get_full_path(options.dmdPath, parser.oldcwd)
-
-        if options.dmd and not options.dmdPath:
-            if build_obj:
-                options.dmdPath = build_obj.bindir
-            else:
-                parser.error(
-                    "could not find dmd libraries, specify them with --dmd-path")
-
         if options.utilityPath:
             options.utilityPath = self.get_full_path(options.utilityPath, parser.oldcwd)
 
         if options.certPath:
             options.certPath = self.get_full_path(options.certPath, parser.oldcwd)
         elif build_obj:
             options.certPath = os.path.join(build_obj.topsrcdir, 'build', 'pgo', 'certs')
 
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -1617,17 +1617,16 @@ toolbar#nav-bar {
             ubsanPath = SCRIPT_DIR
         else:
             ubsanPath = None
 
         browserEnv = self.environment(
             xrePath=options.xrePath,
             env=env,
             debugger=debugger,
-            dmdPath=options.dmdPath,
             lsanPath=lsanPath,
             ubsanPath=ubsanPath)
 
         if hasattr(options, "topsrcdir"):
             browserEnv["MOZ_DEVELOPER_REPO_DIR"] = options.topsrcdir
         if hasattr(options, "topobjdir"):
             browserEnv["MOZ_DEVELOPER_OBJ_DIR"] = options.topobjdir
 
--- a/testing/mochitest/runtestsremote.py
+++ b/testing/mochitest/runtestsremote.py
@@ -351,23 +351,16 @@ def run_test_harness(parser, options):
     # can be conditional on android_version.
     androidVersion = dm.shellCheckOutput(['getprop', 'ro.build.version.sdk'])
     log.info(
         "Android sdk version '%s'; will use this to filter manifests" %
         str(androidVersion))
     mozinfo.info['android_version'] = androidVersion
 
     deviceRoot = dm.deviceRoot
-    if options.dmdPath:
-        dmdLibrary = "libdmd.so"
-        dmdPathOnDevice = os.path.join(deviceRoot, dmdLibrary)
-        dm.removeFile(dmdPathOnDevice)
-        dm.pushFile(os.path.join(options.dmdPath, dmdLibrary), dmdPathOnDevice)
-        options.dmdPath = deviceRoot
-
     options.dumpOutputDirectory = deviceRoot
 
     procName = options.app.split('/')[-1]
     dm.killProcess(procName)
     if dm.processExist(procName):
         log.warning("unable to kill %s before running tests!" % procName)
 
     mochitest.mozLogName = "moz.log"
--- a/testing/mozbase/mozrunner/mozrunner/utils.py
+++ b/testing/mozbase/mozrunner/mozrunner/utils.py
@@ -79,17 +79,17 @@ def _find_marionette_in_args(*args, **kw
 
 
 def _raw_log():
     import logging
     return logging.getLogger(__name__)
 
 
 def test_environment(xrePath, env=None, crashreporter=True, debugger=False,
-                     dmdPath=None, lsanPath=None, ubsanPath=None, log=None):
+                     lsanPath=None, ubsanPath=None, log=None):
     """
     populate OS environment variables for mochitest and reftests.
 
     Originally comes from automationutils.py. Don't use that for new code.
     """
 
     env = os.environ.copy() if env is None else env
     log = log or _raw_log()
@@ -97,39 +97,28 @@ def test_environment(xrePath, env=None, 
     assert os.path.isabs(xrePath)
 
     if mozinfo.isMac:
         ldLibraryPath = os.path.join(os.path.dirname(xrePath), "MacOS")
     else:
         ldLibraryPath = xrePath
 
     envVar = None
-    dmdLibrary = None
-    preloadEnvVar = None
     if mozinfo.isUnix:
         envVar = "LD_LIBRARY_PATH"
-        dmdLibrary = "libdmd.so"
-        preloadEnvVar = "LD_PRELOAD"
     elif mozinfo.isMac:
         envVar = "DYLD_LIBRARY_PATH"
-        dmdLibrary = "libdmd.dylib"
-        preloadEnvVar = "DYLD_INSERT_LIBRARIES"
     elif mozinfo.isWin:
         envVar = "PATH"
-        dmdLibrary = "dmd.dll"
-        preloadEnvVar = "MOZ_REPLACE_MALLOC_LIB"
     if envVar:
         envValue = ((env.get(envVar), str(ldLibraryPath))
                     if mozinfo.isWin
-                    else (ldLibraryPath, dmdPath, env.get(envVar)))
+                    else (ldLibraryPath, env.get(envVar)))
         env[envVar] = os.path.pathsep.join([path for path in envValue if path])
 
-    if dmdPath and dmdLibrary and preloadEnvVar:
-        env[preloadEnvVar] = os.path.join(dmdPath, dmdLibrary)
-
     # crashreporter
     env['GNOME_DISABLE_CRASH_DIALOG'] = '1'
     env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1'
 
     if crashreporter and not debugger:
         env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
         env['MOZ_CRASHREPORTER'] = '1'
     else:
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -648,33 +648,18 @@ class XPCShellTestThread(Thread):
         cmdC = ['-e', 'const _JSCOV_DIR = null']
         if self.jscovdir:
             cmdC = ['-e', 'const _JSCOV_DIR = "%s"' % self.jscovdir.replace('\\', '/')]
             self.complete_command = cmdH + cmdT + cmdI + cmdC + args
         else:
             self.complete_command = cmdH + cmdT + cmdI + args
 
         if self.test_object.get('dmd') == 'true':
-            if sys.platform.startswith('linux'):
-                preloadEnvVar = 'LD_PRELOAD'
-                libdmd = os.path.join(self.xrePath, 'libdmd.so')
-            elif sys.platform == 'osx' or sys.platform == 'darwin':
-                preloadEnvVar = 'DYLD_INSERT_LIBRARIES'
-                # self.xrePath is <prefix>/Contents/Resources.
-                # We need <prefix>/Contents/MacOS/libdmd.dylib.
-                contents_dir = os.path.dirname(self.xrePath)
-                libdmd = os.path.join(contents_dir, 'MacOS', 'libdmd.dylib')
-            elif sys.platform == 'win32':
-                preloadEnvVar = 'MOZ_REPLACE_MALLOC_LIB'
-                libdmd = os.path.join(self.xrePath, 'dmd.dll')
-
             self.env['PYTHON'] = sys.executable
             self.env['BREAKPAD_SYMBOLS_PATH'] = self.symbolsPath
-            self.env['DMD_PRELOAD_VAR'] = preloadEnvVar
-            self.env['DMD_PRELOAD_VALUE'] = libdmd
 
         if self.test_object.get('subprocess') == 'true':
             self.env['PYTHON'] = sys.executable
 
         if self.test_object.get('headless', False):
             self.env["MOZ_HEADLESS"] = '1'
             self.env["DISPLAY"] = '77'  # Set a fake display.