Bug 1420355 - Statically link DMD. r?njn draft
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 28 Nov 2017 08:10:48 +0900
changeset 704825 5d7cc9fd8726a0eb9dab24eea92c6d3a55dffa0c
parent 704805 58692386211959bd041f09f855907f598a9e24b4
child 742173 daa72c8b727a6808bb5918ad8a2f91f17d838797
push id91263
push userbmo:mh+mozilla@glandium.org
push dateWed, 29 Nov 2017 02:37:31 +0000
reviewersnjn
bugs1420355
milestone59.0a1
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.