Bug 850332 - Use jemalloc inside mozglue. r=kats,r=mwu
authorMike Hommey <mh+mozilla@glandium.org>
Sun, 17 Mar 2013 08:03:05 +0100
changeset 128892 65a8f7db264875c2a7a62fdd8a30eda4979b5dea
parent 128891 115239c324a0a419e66395080d8ad68a28ec08da
child 128893 0ff383d4a899769deaebc516451ad985509222ca
push id26555
push usermh@glandium.org
push dateTue, 16 Apr 2013 06:24:50 +0000
treeherdermozilla-inbound@0ff383d4a899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, mwu
bugs850332
milestone23.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 850332 - Use jemalloc inside mozglue. r=kats,r=mwu
build/autoconf/android.m4
js/src/build/autoconf/android.m4
mozglue/android/nsGeckoUtils.cpp
mozglue/build/BionicGlue.cpp
mozglue/build/Makefile.in
--- a/build/autoconf/android.m4
+++ b/build/autoconf/android.m4
@@ -249,17 +249,17 @@ if test "$OS_TARGET" = "Android" -a -z "
                 STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
             elif test -e "$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/libstlport_static.a"; then
                 STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
             else
                 AC_MSG_ERROR([Couldn't find path to stlport in the android ndk])
             fi
             STLPORT_SOURCES="$android_ndk/sources/cxx-stl/stlport"
             STLPORT_CPPFLAGS="-I$_objdir/build/stlport -I$android_ndk/sources/cxx-stl/stlport/stlport"
-            STLPORT_LIBS="-lstlport_static"
+            STLPORT_LIBS="-lstlport_static -static-libstdc++"
         elif test "$target" != "arm-android-eabi"; then
             dnl fail if we're not building with NDKr4
             AC_MSG_ERROR([Couldn't find path to stlport in the android ndk])
         fi
     fi
     CXXFLAGS="$CXXFLAGS $STLPORT_CPPFLAGS"
     LDFLAGS="$LDFLAGS $STLPORT_LDFLAGS"
     LIBS="$LIBS $STLPORT_LIBS"
--- a/js/src/build/autoconf/android.m4
+++ b/js/src/build/autoconf/android.m4
@@ -249,17 +249,17 @@ if test "$OS_TARGET" = "Android" -a -z "
                 STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
             elif test -e "$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/libstlport_static.a"; then
                 STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
             else
                 AC_MSG_ERROR([Couldn't find path to stlport in the android ndk])
             fi
             STLPORT_SOURCES="$android_ndk/sources/cxx-stl/stlport"
             STLPORT_CPPFLAGS="-I$_objdir/build/stlport -I$android_ndk/sources/cxx-stl/stlport/stlport"
-            STLPORT_LIBS="-lstlport_static"
+            STLPORT_LIBS="-lstlport_static -static-libstdc++"
         elif test "$target" != "arm-android-eabi"; then
             dnl fail if we're not building with NDKr4
             AC_MSG_ERROR([Couldn't find path to stlport in the android ndk])
         fi
     fi
     CXXFLAGS="$CXXFLAGS $STLPORT_CPPFLAGS"
     LDFLAGS="$LDFLAGS $STLPORT_LDFLAGS"
     LIBS="$LIBS $STLPORT_LIBS"
--- a/mozglue/android/nsGeckoUtils.cpp
+++ b/mozglue/android/nsGeckoUtils.cpp
@@ -1,21 +1,15 @@
 /* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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 <jni.h>
 
-#ifdef MOZ_MEMORY
-// Wrap malloc and free to use jemalloc
-#define malloc __wrap_malloc
-#define free __wrap_free
-#endif
-
 #include <stdlib.h>
 #include <fcntl.h>
 #include "APKOpen.h"
 #include "Zip.h"
 #include "mozilla/RefPtr.h"
 
 extern "C"
 __attribute__ ((visibility("default")))
--- a/mozglue/build/BionicGlue.cpp
+++ b/mozglue/build/BionicGlue.cpp
@@ -4,28 +4,66 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <pthread.h>
 #include <string.h>
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
 #include <android/log.h>
+#include <mozilla/Util.h>
 
 #include <vector>
 
 #define NS_EXPORT __attribute__ ((visibility("default")))
 
 /* Android doesn't have pthread_atfork(), so we need to use our own. */
 struct AtForkFuncs {
   void (*prepare)(void);
   void (*parent)(void);
   void (*child)(void);
 };
-static std::vector<AtForkFuncs> atfork;
+
+/* jemalloc's initialization calls pthread_atfork. When pthread_atfork (see
+ * further below) stores the corresponding data, it's going to allocate memory,
+ * which will loop back to jemalloc's initialization, leading to a dead-lock.
+ * So, for that specific vector, we use a special allocator that returns a
+ * static buffer for small sizes, and force the initial vector capacity to
+ * a size enough to store one atfork function table. */
+template <typename T>
+struct SpecialAllocator: public std::allocator<T>
+{
+  SpecialAllocator(): bufUsed(false) {}
+
+  inline typename std::allocator<T>::pointer allocate(typename std::allocator<T>::size_type n, const void * = 0) {
+    if (!bufUsed && n == 1) {
+      bufUsed = true;
+      return buf.addr();
+    }
+    return reinterpret_cast<T *>(::operator new(sizeof(T) * n));
+  }
+
+  inline void deallocate(typename std::allocator<T>::pointer p, typename std::allocator<T>::size_type n) {
+    if (p == buf.addr())
+      bufUsed = false;
+    else
+      ::operator delete(p);
+  }
+
+  template<typename U>
+  struct rebind {
+    typedef SpecialAllocator<U> other;
+  };
+
+private:
+  mozilla::AlignedStorage2<T> buf;
+  bool bufUsed;
+};
+
+static std::vector<AtForkFuncs, SpecialAllocator<AtForkFuncs> > atfork;
 
 #ifdef MOZ_WIDGET_GONK
 #include "cpuacct.h"
 #define WRAP(x) x
 
 extern "C" NS_EXPORT int
 timer_create(clockid_t, struct sigevent*, timer_t*)
 {
@@ -41,16 +79,18 @@ timer_create(clockid_t, struct sigevent*
 
 extern "C" NS_EXPORT int
 WRAP(pthread_atfork)(void (*prepare)(void), void (*parent)(void), void (*child)(void))
 {
   AtForkFuncs funcs;
   funcs.prepare = prepare;
   funcs.parent = parent;
   funcs.child = child;
+  if (!atfork.capacity())
+    atfork.reserve(1);
   atfork.push_back(funcs);
   return 0;
 }
 
 extern "C" pid_t __fork(void);
 
 extern "C" NS_EXPORT pid_t
 WRAP(fork)(void)
@@ -128,45 +168,82 @@ PR_GetEnvLock(void)
 /* Amazon Kindle Fire HD's libc provides most of the
  * functions in string.h as weak symbols, which dlsym
  * cannot resolve. Thus, we must wrap these functions.
  * See bug 791419.
  */
 
 #ifndef MOZ_WIDGET_GONK
 #include <string.h>
-extern "C" NS_EXPORT void* __wrap_memccpy(void * a0, const void * a1, int a2, size_t a3) { return memccpy(a0, a1, a2, a3); }
-extern "C" NS_EXPORT void* __wrap_memchr(const void * a0, int a1, size_t a2) { return memchr(a0, a1, a2); }
-extern "C" NS_EXPORT void* __wrap_memrchr(const void * a0, int a1, size_t a2) { return memrchr(a0, a1, a2); }
-extern "C" NS_EXPORT int __wrap_memcmp(const void * a0, const void * a1, size_t a2) { return memcmp(a0, a1, a2); }
-extern "C" NS_EXPORT void* __wrap_memcpy(void * a0, const void * a1, size_t a2) { return memcpy(a0, a1, a2); }
-extern "C" NS_EXPORT void* __wrap_memmove(void * a0, const void * a1, size_t a2) { return memmove(a0, a1, a2); }
-extern "C" NS_EXPORT void* __wrap_memset(void * a0, int a1, size_t a2) { return memset(a0, a1, a2); }
-extern "C" NS_EXPORT void* __wrap_memmem(const void * a0, size_t a1, const void * a2, size_t a3) { return memmem(a0, a1, a2, a3); }
-extern "C" NS_EXPORT void __wrap_memswap(void * a0, void * a1, size_t a2) { memswap(a0, a1, a2); }
-extern "C" NS_EXPORT char* __wrap_index(const char * a0, int a1) { return index(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strchr(const char * a0, int a1) { return strchr(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strrchr(const char * a0, int a1) { return strrchr(a0, a1); }
-extern "C" NS_EXPORT size_t __wrap_strlen(const char * a0) { return strlen(a0); }
-extern "C" NS_EXPORT int __wrap_strcmp(const char * a0, const char * a1) { return strcmp(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strcpy(char * a0, const char * a1) { return strcpy(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strcat(char * a0, const char * a1) { return strcat(a0, a1); }
-extern "C" NS_EXPORT int __wrap_strcasecmp(const char * a0, const char * a1) { return strcasecmp(a0, a1); }
-extern "C" NS_EXPORT int __wrap_strncasecmp(const char * a0, const char * a1, size_t a2) { return strncasecmp(a0, a1, a2); }
-extern "C" NS_EXPORT char* __wrap_strstr(const char * a0, const char * a1) { return strstr(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strcasestr(const char * a0, const char * a1) { return strcasestr(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strtok(char * a0, const char * a1) { return strtok(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strtok_r(char * a0, const char * a1, char** a2) { return strtok_r(a0, a1, a2); }
-extern "C" NS_EXPORT char* __wrap_strerror(int a0) { return strerror(a0); }
-extern "C" NS_EXPORT int __wrap_strerror_r(int a0, char * a1, size_t a2) { return strerror_r(a0, a1, a2); }
-extern "C" NS_EXPORT size_t __wrap_strnlen(const char * a0, size_t a1) { return strnlen(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strncat(char * a0, const char * a1, size_t a2) { return strncat(a0, a1, a2); }
-extern "C" NS_EXPORT int __wrap_strncmp(const char * a0, const char * a1, size_t a2) { return strncmp(a0, a1, a2); }
-extern "C" NS_EXPORT char* __wrap_strncpy(char * a0, const char * a1, size_t a2) { return strncpy(a0, a1, a2); }
-extern "C" NS_EXPORT size_t __wrap_strlcat(char * a0, const char * a1, size_t a2) { return strlcat(a0, a1, a2); }
-extern "C" NS_EXPORT size_t __wrap_strlcpy(char * a0, const char * a1, size_t a2) { return strlcpy(a0, a1, a2); }
-extern "C" NS_EXPORT size_t __wrap_strcspn(const char * a0, const char * a1) { return strcspn(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strpbrk(const char * a0, const char * a1) { return strpbrk(a0, a1); }
-extern "C" NS_EXPORT char* __wrap_strsep(char ** a0, const char * a1) { return strsep(a0, a1); }
-extern "C" NS_EXPORT size_t __wrap_strspn(const char * a0, const char * a1) { return strspn(a0, a1); }
-extern "C" NS_EXPORT int __wrap_strcoll(const char * a0, const char * a1) { return strcoll(a0, a1); }
-extern "C" NS_EXPORT size_t __wrap_strxfrm(char * a0, const char * a1, size_t a2) { return strxfrm(a0, a1, a2); }
+extern "C" NS_EXPORT void* __real_memccpy(void * a0, const void * a1, int a2, size_t a3);
+extern "C" NS_EXPORT void* __real_memchr(const void * a0, int a1, size_t a2);
+extern "C" NS_EXPORT void* __real_memrchr(const void * a0, int a1, size_t a2);
+extern "C" NS_EXPORT int __real_memcmp(const void * a0, const void * a1, size_t a2);
+extern "C" NS_EXPORT void* __real_memcpy(void * a0, const void * a1, size_t a2);
+extern "C" NS_EXPORT void* __real_memmove(void * a0, const void * a1, size_t a2);
+extern "C" NS_EXPORT void* __real_memset(void * a0, int a1, size_t a2);
+extern "C" NS_EXPORT void* __real_memmem(const void * a0, size_t a1, const void * a2, size_t a3);
+extern "C" NS_EXPORT void __real_memswap(void * a0, void * a1, size_t a2);
+extern "C" NS_EXPORT char* __real_index(const char * a0, int a1);
+extern "C" NS_EXPORT char* __real_strchr(const char * a0, int a1);
+extern "C" NS_EXPORT char* __real_strrchr(const char * a0, int a1);
+extern "C" NS_EXPORT size_t __real_strlen(const char * a0);
+extern "C" NS_EXPORT int __real_strcmp(const char * a0, const char * a1);
+extern "C" NS_EXPORT char* __real_strcpy(char * a0, const char * a1);
+extern "C" NS_EXPORT char* __real_strcat(char * a0, const char * a1);
+extern "C" NS_EXPORT int __real_strcasecmp(const char * a0, const char * a1);
+extern "C" NS_EXPORT int __real_strncasecmp(const char * a0, const char * a1, size_t a2);
+extern "C" NS_EXPORT char* __real_strstr(const char * a0, const char * a1);
+extern "C" NS_EXPORT char* __real_strcasestr(const char * a0, const char * a1);
+extern "C" NS_EXPORT char* __real_strtok(char * a0, const char * a1);
+extern "C" NS_EXPORT char* __real_strtok_r(char * a0, const char * a1, char** a2);
+extern "C" NS_EXPORT char* __real_strerror(int a0);
+extern "C" NS_EXPORT int __real_strerror_r(int a0, char * a1, size_t a2);
+extern "C" NS_EXPORT size_t __real_strnlen(const char * a0, size_t a1);
+extern "C" NS_EXPORT char* __real_strncat(char * a0, const char * a1, size_t a2);
+extern "C" NS_EXPORT int __real_strncmp(const char * a0, const char * a1, size_t a2);
+extern "C" NS_EXPORT char* __real_strncpy(char * a0, const char * a1, size_t a2);
+extern "C" NS_EXPORT size_t __real_strlcat(char * a0, const char * a1, size_t a2);
+extern "C" NS_EXPORT size_t __real_strlcpy(char * a0, const char * a1, size_t a2);
+extern "C" NS_EXPORT size_t __real_strcspn(const char * a0, const char * a1);
+extern "C" NS_EXPORT char* __real_strpbrk(const char * a0, const char * a1);
+extern "C" NS_EXPORT char* __real_strsep(char ** a0, const char * a1);
+extern "C" NS_EXPORT size_t __real_strspn(const char * a0, const char * a1);
+extern "C" NS_EXPORT int __real_strcoll(const char * a0, const char * a1);
+extern "C" NS_EXPORT size_t __real_strxfrm(char * a0, const char * a1, size_t a2);
+
+extern "C" NS_EXPORT void* __wrap_memccpy(void * a0, const void * a1, int a2, size_t a3) { return __real_memccpy(a0, a1, a2, a3); }
+extern "C" NS_EXPORT void* __wrap_memchr(const void * a0, int a1, size_t a2) { return __real_memchr(a0, a1, a2); }
+extern "C" NS_EXPORT void* __wrap_memrchr(const void * a0, int a1, size_t a2) { return __real_memrchr(a0, a1, a2); }
+extern "C" NS_EXPORT int __wrap_memcmp(const void * a0, const void * a1, size_t a2) { return __real_memcmp(a0, a1, a2); }
+extern "C" NS_EXPORT void* __wrap_memcpy(void * a0, const void * a1, size_t a2) { return __real_memcpy(a0, a1, a2); }
+extern "C" NS_EXPORT void* __wrap_memmove(void * a0, const void * a1, size_t a2) { return __real_memmove(a0, a1, a2); }
+extern "C" NS_EXPORT void* __wrap_memset(void * a0, int a1, size_t a2) { return __real_memset(a0, a1, a2); }
+extern "C" NS_EXPORT void* __wrap_memmem(const void * a0, size_t a1, const void * a2, size_t a3) { return __real_memmem(a0, a1, a2, a3); }
+extern "C" NS_EXPORT void __wrap_memswap(void * a0, void * a1, size_t a2) { __real_memswap(a0, a1, a2); }
+extern "C" NS_EXPORT char* __wrap_index(const char * a0, int a1) { return __real_index(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strchr(const char * a0, int a1) { return __real_strchr(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strrchr(const char * a0, int a1) { return __real_strrchr(a0, a1); }
+extern "C" NS_EXPORT size_t __wrap_strlen(const char * a0) { return __real_strlen(a0); }
+extern "C" NS_EXPORT int __wrap_strcmp(const char * a0, const char * a1) { return __real_strcmp(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strcpy(char * a0, const char * a1) { return __real_strcpy(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strcat(char * a0, const char * a1) { return __real_strcat(a0, a1); }
+extern "C" NS_EXPORT int __wrap_strcasecmp(const char * a0, const char * a1) { return __real_strcasecmp(a0, a1); }
+extern "C" NS_EXPORT int __wrap_strncasecmp(const char * a0, const char * a1, size_t a2) { return __real_strncasecmp(a0, a1, a2); }
+extern "C" NS_EXPORT char* __wrap_strstr(const char * a0, const char * a1) { return __real_strstr(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strcasestr(const char * a0, const char * a1) { return __real_strcasestr(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strtok(char * a0, const char * a1) { return __real_strtok(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strtok_r(char * a0, const char * a1, char** a2) { return __real_strtok_r(a0, a1, a2); }
+extern "C" NS_EXPORT char* __wrap_strerror(int a0) { return __real_strerror(a0); }
+extern "C" NS_EXPORT int __wrap_strerror_r(int a0, char * a1, size_t a2) { return __real_strerror_r(a0, a1, a2); }
+extern "C" NS_EXPORT size_t __wrap_strnlen(const char * a0, size_t a1) { return __real_strnlen(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strncat(char * a0, const char * a1, size_t a2) { return __real_strncat(a0, a1, a2); }
+extern "C" NS_EXPORT int __wrap_strncmp(const char * a0, const char * a1, size_t a2) { return __real_strncmp(a0, a1, a2); }
+extern "C" NS_EXPORT char* __wrap_strncpy(char * a0, const char * a1, size_t a2) { return __real_strncpy(a0, a1, a2); }
+extern "C" NS_EXPORT size_t __wrap_strlcat(char * a0, const char * a1, size_t a2) { return __real_strlcat(a0, a1, a2); }
+extern "C" NS_EXPORT size_t __wrap_strlcpy(char * a0, const char * a1, size_t a2) { return __real_strlcpy(a0, a1, a2); }
+extern "C" NS_EXPORT size_t __wrap_strcspn(const char * a0, const char * a1) { return __real_strcspn(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strpbrk(const char * a0, const char * a1) { return __real_strpbrk(a0, a1); }
+extern "C" NS_EXPORT char* __wrap_strsep(char ** a0, const char * a1) { return __real_strsep(a0, a1); }
+extern "C" NS_EXPORT size_t __wrap_strspn(const char * a0, const char * a1) { return __real_strspn(a0, a1); }
+extern "C" NS_EXPORT int __wrap_strcoll(const char * a0, const char * a1) { return __real_strcoll(a0, a1); }
+extern "C" NS_EXPORT size_t __wrap_strxfrm(char * a0, const char * a1, size_t a2) { return __real_strxfrm(a0, a1, a2); }
 #endif
--- a/mozglue/build/Makefile.in
+++ b/mozglue/build/Makefile.in
@@ -110,17 +110,17 @@ ifeq (arm, $(TARGET_CPU))
 EXTRA_DSO_LDOPTS += -Wl,-version-script,$(srcdir)/arm-eabi-filter
 endif
 
 endif
 
 SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,mfbt,$(DEPTH)/mfbt)
 
 ifeq (Android, $(OS_TARGET))
-WRAP_LDFLAGS =
+WRAP_LDFLAGS := $(filter -Wl%,$(WRAP_LDFLAGS))
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 ifdef MOZ_MEMORY
 ifeq (WINNT,$(OS_TARGET))
 # Roll our own custom logic here for the import library