Bug 557935: Show jemalloc stats in about:memory on linux. r=vlad
authorChris Jones <jones.chris.g@gmail.com>
Wed, 26 May 2010 14:40:52 -0500
changeset 42837 f223c7d06f91c3839b9f62c1d67a24978609da3f
parent 42836 cb0e5f6d0a1777ef3281fb2838670f4ab5188b08
child 42838 42f90d3591da0463928d048652b70fac602ce3c2
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs557935
milestone1.9.3a5pre
Bug 557935: Show jemalloc stats in about:memory on linux. r=vlad
memory/jemalloc/Makefile.in
memory/jemalloc/jemalloc.h
memory/jemalloc/jemalloc_types.h
xpcom/base/Makefile.in
xpcom/base/nsMemoryReporterManager.cpp
--- a/memory/jemalloc/Makefile.in
+++ b/memory/jemalloc/Makefile.in
@@ -87,30 +87,30 @@ endif
 	$(foreach i,dll mt xdll xmt,$(EXTRACT_CMD))
 # truly awful
 #XXX: get ed into mozillabuild, bug 415123
 	$(PERL) $(srcdir)/apply-ed-patches.pl $(srcdir)/$(CRTDIFF) \
 	$(CRT_OBJ_DIR) $(srcdir)/ed.exe
 
 $(MOZ_CRT_DLL): \
   $(CRT_OBJ_DIR)/jemalloc.c $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h \
-  $(srcdir)/rb.h
-	cp $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h $(srcdir)/rb.h \
+  $(srcdir)/jemalloc_types.h $(srcdir)/rb.h
+	cp $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h $(srcdir)/jemalloc_types.h $(srcdir)/rb.h \
 	$(CRT_OBJ_DIR)
 # this pretty much sucks, but nmake and make don't play well together
 	$(PYTHON) $(srcdir)/build-crt.py $(CRT_OBJ_DIR)
 # XXX: these don't link right for some reason; the problem is likely
 # that  not all the standard symbols are exported; looks like MSFT
 # never updated the sample.def files; could probably fix if someone
 # were ever bored enough. :-)
 	rm -f $(addsuffix .lib, $(addprefix $(CRT_OBJ_DIR)/build/intel/, $(MOZ_CRT_STATIC_LIBS)))
 	rm -f $(addsuffix .pdb, $(addprefix $(CRT_OBJ_DIR)/build/intel/, $(MOZ_CRT_STATIC_LIBS)))
 
 # but still export jemalloc.h
-EXPORTS = jemalloc.h
+EXPORTS = jemalloc.h jemalloc_types.h
 
 else # Not Windows
 
 MODULE_OPTIMIZE_FLAGS = -O2
 ifeq ($(OS_ARCH),SunOS)
 ifndef GNU_CC
 MODULE_OPTIMIZE_FLAGS = -xO5
 endif
@@ -122,17 +122,17 @@ LIBRARY_NAME	= jemalloc
 # init function is used on that platform.
 ifeq ($(OS_ARCH),Darwin)
 FORCE_SHARED_LIB= 1
 else
 DIST_INSTALL = 1
 FORCE_STATIC_LIB= 1
 endif
 
-EXPORTS = jemalloc.h
+EXPORTS = jemalloc.h jemalloc_types.h
 CSRCS   = jemalloc.c
 
 #XXX: PGO on Linux causes problems here
 # See bug 419470
 NO_PROFILE_GUIDED_OPTIMIZE = 1
 endif
 
 ifdef WRAP_MALLOC_CFLAGS
--- a/memory/jemalloc/jemalloc.h
+++ b/memory/jemalloc/jemalloc.h
@@ -27,63 +27,24 @@
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef _JEMALLOC_H_
 #define _JEMALLOC_H_
 
-/* grab size_t */
-#ifdef _MSC_VER
-#include <crtdefs.h>
-#else
-#include <stddef.h>
-#endif
+#include "jemalloc_types.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef unsigned char jemalloc_bool;
-
 extern const char *_malloc_options;
 
-/*
- * jemalloc_stats() is not a stable interface.  When using jemalloc_stats_t, be
- * sure that the compiled results of jemalloc.c are in sync with this header
- * file.
- */
-typedef struct {
-	/*
-	 * Run-time configuration settings.
-	 */
-	jemalloc_bool	opt_abort;	/* abort(3) on error? */
-	jemalloc_bool	opt_junk;	/* Fill allocated/free memory with 0xa5/0x5a? */
-	jemalloc_bool	opt_utrace;	/* Trace all allocation events? */
-	jemalloc_bool	opt_sysv;	/* SysV semantics? */
-	jemalloc_bool	opt_xmalloc;	/* abort(3) on OOM? */
-	jemalloc_bool	opt_zero;	/* Fill allocated memory with 0x0? */
-	size_t	narenas;	/* Number of arenas. */
-	size_t	balance_threshold; /* Arena contention rebalance threshold. */
-	size_t	quantum;	/* Allocation quantum. */
-	size_t	small_max;	/* Max quantum-spaced allocation size. */
-	size_t	large_max;	/* Max sub-chunksize allocation size. */
-	size_t	chunksize;	/* Size of each virtual memory mapping. */
-	size_t	dirty_max;	/* Max dirty pages per arena. */
-
-	/*
-	 * Current memory usage statistics.
-	 */
-	size_t	mapped;		/* Bytes mapped (not necessarily committed). */
-	size_t	committed;	/* Bytes committed (readable/writable). */
-	size_t	allocated;	/* Bytes allocted (in use by application). */
-	size_t	dirty;		/* Bytes dirty (committed unused pages). */
-} jemalloc_stats_t;
-
 /* Darwin and Linux already have memory allocation functions */
 #if (!defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_MEMORY_LINUX))
 void	*malloc(size_t size);
 void	*valloc(size_t size);
 void	*calloc(size_t num, size_t size);
 void	*realloc(void *ptr, size_t size);
 void	free(void *ptr);
 int	posix_memalign(void **memptr, size_t alignment, size_t size);
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/jemalloc_types.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */
+/* vim:set softtabstop=8 shiftwidth=8: */
+/*-
+ * Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice(s), this list of conditions and the following disclaimer as
+ *    the first lines of this file unmodified other than the possible
+ *    addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice(s), this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _JEMALLOC_TYPES_H_
+#define _JEMALLOC_TYPES_H_
+
+/* grab size_t */
+#ifdef _MSC_VER
+#include <crtdefs.h>
+#else
+#include <stddef.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char jemalloc_bool;
+
+/*
+ * jemalloc_stats() is not a stable interface.  When using jemalloc_stats_t, be
+ * sure that the compiled results of jemalloc.c are in sync with this header
+ * file.
+ */
+typedef struct {
+	/*
+	 * Run-time configuration settings.
+	 */
+	jemalloc_bool	opt_abort;	/* abort(3) on error? */
+	jemalloc_bool	opt_junk;	/* Fill allocated/free memory with 0xa5/0x5a? */
+	jemalloc_bool	opt_utrace;	/* Trace all allocation events? */
+	jemalloc_bool	opt_sysv;	/* SysV semantics? */
+	jemalloc_bool	opt_xmalloc;	/* abort(3) on OOM? */
+	jemalloc_bool	opt_zero;	/* Fill allocated memory with 0x0? */
+	size_t	narenas;	/* Number of arenas. */
+	size_t	balance_threshold; /* Arena contention rebalance threshold. */
+	size_t	quantum;	/* Allocation quantum. */
+	size_t	small_max;	/* Max quantum-spaced allocation size. */
+	size_t	large_max;	/* Max sub-chunksize allocation size. */
+	size_t	chunksize;	/* Size of each virtual memory mapping. */
+	size_t	dirty_max;	/* Max dirty pages per arena. */
+
+	/*
+	 * Current memory usage statistics.
+	 */
+	size_t	mapped;		/* Bytes mapped (not necessarily committed). */
+	size_t	committed;	/* Bytes committed (readable/writable). */
+	size_t	allocated;	/* Bytes allocted (in use by application). */
+	size_t	dirty;		/* Bytes dirty (committed unused pages). */
+} jemalloc_stats_t;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* _JEMALLOC_TYPES_H_ */
--- a/xpcom/base/Makefile.in
+++ b/xpcom/base/Makefile.in
@@ -44,16 +44,21 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= xpcom
 XPIDL_MODULE	= xpcom_base
 LIBRARY_NAME	= xpcombase_s
 GRE_MODULE	= 1
 MOZILLA_INTERNAL_API =1
 LIBXUL_LIBRARY = 1
 
+# TODO: we do this in crashreporter too, should be centralized
+ifeq ($(OS_ARCH),Linux)
+DEFINES += -DXP_LINUX
+endif
+
 CPPSRCS		= \
 		nsVersionComparatorImpl.cpp \
 		nsConsoleMessage.cpp \
 		nsConsoleService.cpp \
 		nsDebugImpl.cpp \
 		nsErrorService.cpp \
 		nsExceptionService.cpp \
 		nsMemoryImpl.cpp \
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -43,29 +43,40 @@
 #include "nsArrayEnumerator.h"
 
 /**
  ** memory reporter implementation for jemalloc and OSX malloc,
  ** to obtain info on total memory in use (that we know about,
  ** at least -- on OSX, there are sometimes other zones in use).
  **/
 
-/* Because of the way that jemalloc is linked on linux, we can't
- * get to jemalloc_stats().  So just do this on Windows until
- * that's fixed.
- */
-#if defined(MOZ_MEMORY) && defined(XP_WIN)
-#define HAVE_JEMALLOC_STATS 1
-#else
-#undef HAVE_JEMALLOC_STATS
-#endif
+#if defined(MOZ_MEMORY)
+#  if defined(XP_WIN) || defined(SOLARIS)
+#    define HAVE_JEMALLOC_STATS 1
+#    include "jemalloc.h"
+#  elif defined(XP_LINUX)
+#    define HAVE_JEMALLOC_STATS 1
+#    include "jemalloc_types.h"
+// jemalloc is directly linked into firefox-bin; libxul doesn't link
+// with it.  So if we tried to use jemalloc_stats directly here, it
+// wouldn't be defined.  Instead, we don't include the jemalloc header
+// and weakly link against jemalloc_stats.
+//
+// NB: we don't null-check this symbol at runtime because we expect it
+// to have been resolved.  If it hasn't, the crash jumping to NULL
+// will indicate the bug.
+extern "C" {
+extern void jemalloc_stats(jemalloc_stats_t* stats)
+  NS_VISIBILITY_DEFAULT __attribute__((weak));
+}
+#  endif  // XP_LINUX
+#endif  // MOZ_MEMORY
 
-#if defined(HAVE_JEMALLOC_STATS)
-#define HAVE_MALLOC_REPORTERS 1
-#include "jemalloc.h"
+#if HAVE_JEMALLOC_STATS
+#  define HAVE_MALLOC_REPORTERS 1
 
 PRInt64 getMallocMapped(void *) {
     jemalloc_stats_t stats;
     jemalloc_stats(&stats);
     return (PRInt64) stats.mapped;
 }
 
 PRInt64 getMallocAllocated(void *) {