Bug 1420355 - Allow to statically link replace-malloc libraries. r?njn draft
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 23 Nov 2017 17:24:19 +0900
changeset 704805 58692386211959bd041f09f855907f598a9e24b4
parent 704804 3ca7b958c8db0819ebdd54fd705ff87d76b5ebf7
child 704806 f75f54e56e182f337d690ff2acf3a1a00735194b
child 704825 5d7cc9fd8726a0eb9dab24eea92c6d3a55dffa0c
push id91252
push userbmo:mh+mozilla@glandium.org
push dateWed, 29 Nov 2017 00:22:21 +0000
reviewersnjn
bugs1420355
milestone59.0a1
Bug 1420355 - Allow to statically link replace-malloc libraries. r?njn And statically link logalloc. Statically linking is the default, except when building with --enable-project=memory, allowing to use the generated libraries from such builds with Firefox.
build/moz.configure/memory.configure
memory/build/moz.build
memory/build/mozjemalloc.cpp
memory/build/replace_malloc.h
memory/replace/logalloc/README
memory/replace/logalloc/logalloc.mozbuild
memory/replace/logalloc/moz.build
memory/replace/logalloc/replay/Makefile.in
memory/replace/logalloc/replay/moz.build
memory/replace/moz.build
--- a/build/moz.configure/memory.configure
+++ b/build/moz.configure/memory.configure
@@ -57,8 +57,19 @@ def replace_malloc(value, jemalloc, mile
         return True
     if milestone.is_nightly and jemalloc and build_project != 'js':
         return True
 
 
 set_config('MOZ_REPLACE_MALLOC', replace_malloc)
 set_define('MOZ_REPLACE_MALLOC', replace_malloc)
 add_old_configure_assignment('MOZ_REPLACE_MALLOC', replace_malloc)
+
+
+@depends(replace_malloc, build_project)
+def replace_malloc_static(replace_malloc, build_project):
+    # Default to statically linking replace-malloc libraries that can be
+    # statically linked, except when building with --enable-project=memory.
+    if replace_malloc and build_project != 'memory':
+        return True
+
+
+set_config('MOZ_REPLACE_MALLOC_STATIC', replace_malloc_static)
--- a/memory/build/moz.build
+++ b/memory/build/moz.build
@@ -44,9 +44,12 @@ if CONFIG['OS_TARGET'] == 'Android' and 
     ]
 
 if CONFIG['MOZ_BUILD_APP'] != 'memory':
     FINAL_LIBRARY = 'mozglue'
 
 if CONFIG['_MSC_VER']:
     CXXFLAGS += ['-wd4273'] # inconsistent dll linkage (bug 558163)
 
+if CONFIG['MOZ_REPLACE_MALLOC_STATIC']:
+    DEFINES['MOZ_REPLACE_MALLOC_STATIC'] = True
+
 DisableStlWrapping()
--- a/memory/build/mozjemalloc.cpp
+++ b/memory/build/mozjemalloc.cpp
@@ -4869,36 +4869,56 @@ replace_malloc_handle()
 #define REPLACE_MALLOC_GET_INIT_FUNC(handle)                                   \
   (replace_init_impl_t*)dlsym(handle, "replace_init")
 
 #endif
 
 static void
 replace_malloc_init_funcs();
 
+#ifdef MOZ_REPLACE_MALLOC_STATIC
+extern "C" void
+logalloc_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;
+}
+
 // Below is the malloc implementation overriding jemalloc and calling the
 // replacement functions if they exist.
 static bool gReplaceMallocInitialized = false;
 static ReplaceMallocBridge* gReplaceMallocBridge = nullptr;
 static void
 init()
 {
+#ifdef MOZ_REPLACE_MALLOC_STATIC
+  malloc_table_t initialTable = gReplaceMallocTable;
+#endif
+
 #ifdef MOZ_DYNAMIC_REPLACE_INIT
   replace_malloc_handle_t handle = replace_malloc_handle();
   if (handle) {
     replace_init = REPLACE_MALLOC_GET_INIT_FUNC(handle);
   }
 #endif
 
   // Set this *before* calling replace_init, otherwise if replace_init calls
   // malloc() we'll get an infinite loop.
   gReplaceMallocInitialized = true;
   if (replace_init) {
     replace_init(&gReplaceMallocTable, &gReplaceMallocBridge);
   }
+#ifdef MOZ_REPLACE_MALLOC_STATIC
+  if (Equals(initialTable, gReplaceMallocTable)) {
+    logalloc_init(&gReplaceMallocTable, &gReplaceMallocBridge);
+  }
+#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/build/replace_malloc.h
+++ b/memory/build/replace_malloc.h
@@ -71,25 +71,36 @@
 
 #define REPLACE_MALLOC_IMPL
 
 #include "replace_malloc_bridge.h"
 
 // Implementing a replace-malloc library is incompatible with using mozalloc.
 #define MOZ_NO_MOZALLOC 1
 
+#include "mozilla/MacroArgs.h"
 #include "mozilla/Types.h"
 
 MOZ_BEGIN_EXTERN_C
 
 // MOZ_REPLACE_WEAK is only defined in mozjemalloc.cpp. Normally including
 // this header will add function definitions.
 #ifndef MOZ_REPLACE_WEAK
 #define MOZ_REPLACE_WEAK
 #endif
 
+// When building a replace-malloc library for static linking, we want
+// each to have a different name for their "public" functions.
+// The build system defines MOZ_REPLACE_MALLOC_PREFIX in that case.
+#ifdef MOZ_REPLACE_MALLOC_PREFIX
+#define replace_init MOZ_CONCAT(MOZ_REPLACE_MALLOC_PREFIX, _init)
+#define MOZ_REPLACE_PUBLIC
+#else
+#define MOZ_REPLACE_PUBLIC MOZ_EXPORT
+#endif
+
 // Replace-malloc library initialization function. See top of this file
-MOZ_EXPORT void
+MOZ_REPLACE_PUBLIC void
 replace_init(malloc_table_t*, struct ReplaceMallocBridge**) MOZ_REPLACE_WEAK;
 
 MOZ_END_EXTERN_C
 
 #endif // replace_malloc_h
--- a/memory/replace/logalloc/README
+++ b/memory/replace/logalloc/README
@@ -1,29 +1,17 @@
 Logalloc is a replace-malloc library for Firefox (see
 memory/build/replace_malloc.h) that dumps a log of memory allocations to a
 given file descriptor or file name. That log can then be replayed against
 Firefox's default memory allocator independently or through another
 replace-malloc library, allowing the testing of other allocators under the
 exact same workload.
 
-To get an allocation log the following environment variables need to be set
-when starting Firefox:
-- on Linux:
-  LD_PRELOAD=/path/to/liblogalloc.so
-- on Mac OSX:
-  DYLD_INSERT_LIBRARIES=/path/to/liblogalloc.dylib
-- on Windows:
-  MOZ_REPLACE_MALLOC_LIB=/path/to/logalloc.dll
-- on Android:
-  MOZ_REPLACE_MALLOC_LIB=/path/to/liblogalloc.so
-  (see https://wiki.mozilla.org/Mobile/Fennec/Android#Arguments_and_Environment_Variables
-  for how to pass environment variables to Firefox for Android)
-
-- on all platforms:
+To get an allocation log the following environment variable when starting
+Firefox:
   MALLOC_LOG=/path/to/log-file
   or
   MALLOC_LOG=number
 
 When MALLOC_LOG is a number below 10000, it is considered as a file
 descriptor number that is fed to Firefox when it is started. Otherwise,
 it is considered as a file name.
 
--- a/memory/replace/logalloc/logalloc.mozbuild
+++ b/memory/replace/logalloc/logalloc.mozbuild
@@ -24,12 +24,12 @@ if CONFIG['OS_TARGET'] == 'WINNT':
 else:
     SOURCES += [
         '../../../ipc/chromium/src/base/lock_impl_posix.cc',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 # Android doesn't have pthread_atfork, but we have our own in mozglue.
-if CONFIG['OS_TARGET'] == 'Android':
+if CONFIG['OS_TARGET'] == 'Android' and FORCE_SHARED_LIB:
     USE_LIBS += [
         'mozglue',
     ]
--- a/memory/replace/logalloc/moz.build
+++ b/memory/replace/logalloc/moz.build
@@ -1,14 +1,14 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-SharedLibrary('logalloc')
+ReplaceMalloc('logalloc')
 
 include('logalloc.mozbuild')
 
 DIRS += [
     'minimal',
     'replay',
 ]
--- a/memory/replace/logalloc/replay/Makefile.in
+++ b/memory/replace/logalloc/replay/Makefile.in
@@ -11,17 +11,19 @@ LOGALLOC_VAR = MOZ_REPLACE_MALLOC_LIB
 else
 ifeq ($(OS_TARGET),Darwin)
 LOGALLOC_VAR = DYLD_INSERT_LIBRARIES
 else
 LOGALLOC_VAR = LD_PRELOAD
 endif
 endif
 
+ifndef MOZ_REPLACE_MALLOC_STATIC
 LOGALLOC = $(LOGALLOC_VAR)=$(CURDIR)/../$(DLL_PREFIX)logalloc$(DLL_SUFFIX)
+endif
 LOGALLOC_MINIMAL = $(LOGALLOC_VAR)=$(CURDIR)/../minimal/$(DLL_PREFIX)logalloc_minimal$(DLL_SUFFIX)
 
 expected_output.log: $(srcdir)/replay.log
 # The logalloc-replay program will only replay entries from the first pid,
 # so the expected output only contains entries beginning with "1 "
 	grep "^1 " $< > $@
 
 check:: $(srcdir)/replay.log expected_output.log $(srcdir)/expected_output_minimal.log
--- a/memory/replace/logalloc/replay/moz.build
+++ b/memory/replace/logalloc/replay/moz.build
@@ -2,22 +2,26 @@
 # vim: set filetype=python:
 # 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/.
 
 Program('logalloc-replay')
 
 SOURCES += [
-    '../FdPrintf.cpp',
     '/mfbt/Assertions.cpp',
     '/mfbt/Unused.cpp',
     'Replay.cpp',
 ]
 
+if not CONFIG['MOZ_REPLACE_MALLOC_STATIC']:
+    SOURCES += [
+        '../FdPrintf.cpp',
+    ]
+
 LOCAL_INCLUDES += [
     '..',
 ]
 
 # Link replace-malloc and the default allocator.
 USE_LIBS += [
     'memory',
 ]
--- a/memory/replace/moz.build
+++ b/memory/replace/moz.build
@@ -1,12 +1,20 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+@template
+def ReplaceMalloc(name):
+    if CONFIG['MOZ_REPLACE_MALLOC_STATIC']:
+        DEFINES['MOZ_REPLACE_MALLOC_PREFIX'] = name.replace('-', '_')
+        FINAL_LIBRARY = 'memory'
+    else:
+        SharedLibrary(name)
+
 DIRS += [
     'logalloc',
 ]
 
 if CONFIG['MOZ_DMD']:
     DIRS += ['dmd']