diff options
author | glider@chromium.org <glider@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-19 11:53:09 +0000 |
---|---|---|
committer | glider@chromium.org <glider@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-19 11:53:09 +0000 |
commit | ad03b834615460ff0657fbb0ca3de3f50ef8e277 (patch) | |
tree | 0952d2c0919ae85c20ca21318c5a9996b90f9367 /third_party | |
parent | fabc73152475a5b6817e15a4f660fb8bb8f19b48 (diff) | |
download | chromium_src-ad03b834615460ff0657fbb0ca3de3f50ef8e277.zip chromium_src-ad03b834615460ff0657fbb0ca3de3f50ef8e277.tar.gz chromium_src-ad03b834615460ff0657fbb0ca3de3f50ef8e277.tar.bz2 |
Update the tcmalloc vendor branch to r111 (perftools version 1.8)
The major reason for us to switch to this branch is better Mac OS X support.
Please note that this change doesn't affect Chromium builds.
TBR=willchan
Review URL: http://codereview.chromium.org/7430002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93000 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
69 files changed, 3457 insertions, 1479 deletions
diff --git a/third_party/tcmalloc/README.chromium b/third_party/tcmalloc/README.chromium index 70ee5f4..5f92c68 100644 --- a/third_party/tcmalloc/README.chromium +++ b/third_party/tcmalloc/README.chromium @@ -27,8 +27,8 @@ Contents: The current revision is: - Last Changed Rev: 109 - Last Changed Date: 2011-05-20 01:37:12 +0400 (Fri, 20 May 2011) + Last Changed Rev: 111 + Last Changed Date: 2011-07-16 05:07:10 +0400 (Sat, 16 Jul 2011) diff --git a/third_party/tcmalloc/vendor/ChangeLog b/third_party/tcmalloc/vendor/ChangeLog index ee43193..c439360 100644 --- a/third_party/tcmalloc/vendor/ChangeLog +++ b/third_party/tcmalloc/vendor/ChangeLog @@ -1,3 +1,58 @@ +Fri Jul 15 16:10:51 2011 Google Inc. <opensource@google.com> + + * google-perftools: version 1.8 release + * PORTING: (Disabled) support for patching mmap on freebsd (chapp...) + * PORTING: Support volatile __malloc_hook for glibc 2.14 (csilvers) + * PORTING: Use _asm rdtsc and __rdtsc to get cycleclock in windows (koda) + * PORTING: Fix fd vs. HANDLE compiler error on cygwin (csilvers) + * PORTING: Do not test memalign or double-linking on OS X (csilvers) + * PORTING: Actually enable TLS on windows (jontra) + * PORTING: Some work to compile under Native Client (krasin) + * PORTING: deal with pthread_once w/o -pthread on freebsd (csilvers) + * Rearrange libc-overriding to make it easier to port (csilvers) + * Display source locations in pprof disassembly (sanjay) + * BUGFIX: Actually initialize allocator name (mec) + * BUGFIX: Keep track of 'overhead' bytes in malloc reporting (csilvers) + * Allow ignoring one object twice in the leak checker (glider) + * BUGFIX: top10 in pprof should print 10 lines, not 11 (rsc) + * Refactor vdso source files (tipp) + * Some documentation cleanups + * Document MAX_TOTAL_THREAD_CACHE_SIZE <= 1Gb (nsethi) + * Add MallocExtension::GetOwnership(ptr) (csilvers) + * BUGFIX: We were leaving out a needed $(top_srcdir) in the Makefile + * PORTING: Support getting argv0 on OS X + * Add 'weblist' command to pprof: like 'list' but html (sanjay) + * Improve source listing in pprof (sanjay) + * Cap cache sizes to reduce fragmentation (ruemmler) + * Improve performance by capping or increasing sizes (ruemmler) + * Add M{,un}mapReplacmenet hooks into MallocHook (ribrdb) + * Refactored system allocator logic (gangren) + * Include cleanups (csilvers) + * Add TCMALLOC_SMALL_BUT_SLOW support (ruemmler) + * Clarify that tcmalloc stats are MiB (robinson) + * Remove support for non-tcmalloc debugallocation (blount) + * Add a new test: malloc_hook_test (csilvers) + * Change the configure script to be more crosstool-friendly (mcgrathr) + * PORTING: leading-underscore changes to support win64 (csilvers) + * Improve debugallocation tc_malloc_size (csilvers) + * Extend atomicops.h and cyceclock to use ARM V6+ optimized code (sanek) + * Change malloc-hook to use a list-like structure (llib) + * Add flag to use MAP_PRIVATE in memfs_malloc (gangren) + * Windows support for pprof: nul and /usr/bin/file (csilvers) + * TESTING: add test on strdup to tcmalloc_test (csilvers) + * Augment heap-checker to deal with no-inode maps (csilvers) + * Count .dll/.dylib as shared libs in heap-checker (csilvers) + * Disable sys_futex for arm; it's not always reliable (sanek) + * PORTING: change lots of windows/port.h macros to functions + * BUGFIX: Generate correct version# in tcmalloc.h on windows (csilvers) + * PORTING: Some casting to make solaris happier about types (csilvers) + * TESTING: Disable debugallocation_test in 'minimal' mode (csilvers) + * Rewrite debugallocation to be more modular (csilvers) + * Don't try to run the heap-checker under valgrind (ppluzhnikov) + * BUGFIX: Make focused stat %'s relative, not absolute (sanjay) + * BUGFIX: Don't use '//' comments in a C file (csilvers) + * Quiet new-gcc compiler warnings via -Wno-unused-result, etc (csilvers) + Fri Feb 04 15:54:31 2011 Google Inc. <opensource@google.com> * google-perftools: version 1.7 release diff --git a/third_party/tcmalloc/vendor/Makefile.am b/third_party/tcmalloc/vendor/Makefile.am index 5eb4d42..2020fab 100644 --- a/third_party/tcmalloc/vendor/Makefile.am +++ b/third_party/tcmalloc/vendor/Makefile.am @@ -30,6 +30,9 @@ AM_CXXFLAGS += -Wall -Wwrite-strings -Woverloaded-virtual \ -fno-builtin-memalign -fno-builtin-posix_memalign \ -fno-builtin-valloc -fno-builtin-pvalloc endif GCC +if HAVE_W_NO_UNUSED_RESULT +AM_CXXFLAGS += -Wno-unused-result +endif HAVE_W_NO_UNUSED_RESULT # The -no-undefined flag allows libtool to generate shared libraries for # Cygwin and MinGW. LIBSTDCXX_LA_LINKER_FLAG is used to fix a Solaris bug. @@ -255,11 +258,13 @@ LOW_LEVEL_ALLOC_UNITTEST_INCLUDES = src/base/low_level_alloc.h \ src/google/malloc_hook.h \ src/google/malloc_hook_c.h \ src/malloc_hook-inl.h \ + src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h \ $(SPINLOCK_INCLUDES) \ $(LOGGING_INCLUDES) low_level_alloc_unittest_SOURCES = src/base/low_level_alloc.cc \ src/malloc_hook.cc \ - src/maybe_threads.cc \ + $(MAYBE_THREADS_CC) \ src/tests/low_level_alloc_unittest.cc \ $(LOW_LEVEL_ALLOC_UNITTEST_INCLUDES) # By default, MallocHook takes stack traces for use by the heap-checker. @@ -286,11 +291,14 @@ if WITH_STACK_TRACE S_STACKTRACE_INCLUDES = src/stacktrace_config.h \ src/stacktrace_generic-inl.h \ src/stacktrace_libunwind-inl.h \ + src/stacktrace_nacl-inl.h \ src/stacktrace_powerpc-inl.h \ src/stacktrace_x86_64-inl.h \ src/stacktrace_x86-inl.h \ src/stacktrace_win32-inl.h \ + src/base/elf_mem_image.h \ src/base/vdso_support.h + SG_STACKTRACE_INCLUDES = src/google/stacktrace.h STACKTRACE_INCLUDES = $(S_STACKTRACE_INCLUDES) $(SG_STACKTRACE_INCLUDES) googleinclude_HEADERS += $(SG_STACKTRACE_INCLUDES) @@ -298,6 +306,7 @@ googleinclude_HEADERS += $(SG_STACKTRACE_INCLUDES) ### Making the library noinst_LTLIBRARIES += libstacktrace.la libstacktrace_la_SOURCES = src/stacktrace.cc \ + src/base/elf_mem_image.cc \ src/base/vdso_support.cc \ $(STACKTRACE_INCLUDES) libstacktrace_la_LIBADD = $(UNWIND_LIBS) $(LIBSPINLOCK) @@ -363,6 +372,11 @@ S_TCMALLOC_MINIMAL_INCLUDES = src/common.h \ src/sampler.h \ src/central_freelist.h \ src/linked_list.h \ + src/libc_override.h \ + src/libc_override_gcc_and_weak.h \ + src/libc_override_glibc.h \ + src/libc_override_osx.h \ + src/libc_override_redefine.h \ src/page_heap.h \ src/page_heap_allocator.h \ src/span.h \ @@ -372,6 +386,8 @@ S_TCMALLOC_MINIMAL_INCLUDES = src/common.h \ src/stack_trace_table.h \ src/base/thread_annotations.h \ src/malloc_hook-inl.h \ + src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h \ src/maybe_threads.h SG_TCMALLOC_MINIMAL_INCLUDES = src/google/malloc_hook.h \ src/google/malloc_hook_c.h \ @@ -442,6 +458,8 @@ LIBS_TO_WEAKEN += libtcmalloc_minimal.la ## src/google/malloc_hook.h \ ## src/google/malloc_hook_c.h \ ## src/malloc_hook-inl.h \ +## src/malloc_hook_mmap_linux.h \ +## src/malloc_hook_mmap_freebsd.h \ ## src/base/basictypes.h \ ## src/maybe_threads.h ## malloc_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ @@ -597,6 +615,7 @@ endif !ENABLE_STATIC endif !MINGW if !MINGW +if !OSX TESTS += memalign_unittest memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \ src/tcmalloc.h \ @@ -605,6 +624,7 @@ memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \ memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +endif !OSX endif !MINGW TESTS += page_heap_test @@ -727,11 +747,15 @@ malloc_extension_debug_test_CXXFLAGS = $(malloc_extension_test_CXXFLAGS) malloc_extension_debug_test_LDFLAGS = $(malloc_extension_test_LDFLAGS) malloc_extension_debug_test_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) +if !MINGW +if !OSX TESTS += memalign_debug_unittest memalign_debug_unittest_SOURCES = $(memalign_unittest_SOURCES) memalign_debug_unittest_CXXFLAGS = $(memalign_unittest_CXXFLAGS) memalign_debug_unittest_LDFLAGS = $(memalign_unittest_LDFLAGS) memalign_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) +endif !OSX +endif !MINGW TESTS += realloc_debug_unittest realloc_debug_unittest_SOURCES = $(realloc_unittest_SOURCES) @@ -852,14 +876,15 @@ tcmalloc_unittest_LDADD = $(LIBTCMALLOC) liblogging.la $(PTHREAD_LIBS) # This makes sure it's safe to link in both tcmalloc and # tcmalloc_minimal. (One would never do this on purpose, but perhaps # by accident...) When we can compile libprofiler, we also link it in -# to make sure that works too. - -TESTS += tcmalloc_both_unittest -tcmalloc_both_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ - src/tests/testutil.h src/tests/testutil.cc \ - $(TCMALLOC_UNITTEST_INCLUDES) -tcmalloc_both_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) -tcmalloc_both_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +# to make sure that works too. NOTE: On OS X, it's *not* safe to +# link both in (we end up with two copies of every global var, and +# the code tends to pick one arbitrarily), so don't run the test there. +# (We define these outside the 'if' because they're reused below.) +tcmalloc_both_unittest_srcs = src/tests/tcmalloc_unittest.cc \ + src/tests/testutil.h src/tests/testutil.cc \ + $(TCMALLOC_UNITTEST_INCLUDES) +tcmalloc_both_unittest_cflags = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_both_unittest_lflags = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) if WITH_CPU_PROFILER # We want libtcmalloc last on the link line, but due to a bug in # libtool involving convenience libs, they need to come last on the @@ -868,12 +893,19 @@ if WITH_CPU_PROFILER # We also put pthreads after tcmalloc, because some pthread # implementations define their own malloc, and we need to go on the # first linkline to make sure our malloc 'wins'. -tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ - libprofiler.la liblogging.la $(PTHREAD_LIBS) +tcmalloc_both_unittest_ladd = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ + libprofiler.la liblogging.la $(PTHREAD_LIBS) else -tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ - liblogging.la $(PTHREAD_LIBS) +tcmalloc_both_unittest_ladd = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ + liblogging.la $(PTHREAD_LIBS) endif !WITH_CPU_PROFILER +if !OSX +TESTS += tcmalloc_both_unittest +tcmalloc_both_unittest_SOURCES = $(tcmalloc_both_unittest_srcs) +tcmalloc_both_unittest_CXXFLAGS = $(tcmalloc_both_unittest_cflags) +tcmalloc_both_unittest_LDFLAGS = $(tcmalloc_both_unittest_lflags) +tcmalloc_both_unittest_LDADD = $(tcmalloc_both_unittest_ladd) +endif !OSX TESTS += tcmalloc_large_unittest tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc @@ -1221,9 +1253,9 @@ libtcmalloc_and_profiler_la_LDFLAGS = $(PTHREAD_CFLAGS) \ libtcmalloc_and_profiler_la_LIBADD = $(libtcmalloc_la_LIBADD) TESTS += tcmalloc_and_profiler_unittest -tcmalloc_and_profiler_unittest_SOURCES = $(tcmalloc_both_unittest_SOURCES) -tcmalloc_and_profiler_unittest_CXXFLAGS = $(tcmalloc_both_unittest_CXXFLAGS) -tcmalloc_and_profiler_unittest_LDFLAGS = $(tcmalloc_both_unittest_LDFLAGS) +tcmalloc_and_profiler_unittest_SOURCES = $(tcmalloc_both_unittest_srcs) +tcmalloc_and_profiler_unittest_CXXFLAGS = $(tcmalloc_both_unittest_cflags) +tcmalloc_and_profiler_unittest_LDFLAGS = $(tcmalloc_both_unittest_lflags) tcmalloc_and_profiler_unittest_LDADD = libtcmalloc_and_profiler.la LIBS_TO_WEAKEN += libtcmalloc_and_profiler.la @@ -1269,8 +1301,8 @@ libtcmalloc.pc: Makefile packages/rpm/rpm.spec echo '' >> "$@".tmp echo 'Name: $(PACKAGE)' >> "$@".tmp echo 'Version: $(VERSION)' >> "$@".tmp - -grep '^Summary:' packages/rpm/rpm.spec | sed s/^Summary:/Description:/ | head -n1 >> "$@".tmp - -grep '^URL: ' packages/rpm/rpm.spec >> "$@".tmp + -grep '^Summary:' $(top_srcdir)/packages/rpm/rpm.spec | sed s/^Summary:/Description:/ | head -n1 >> "$@".tmp + -grep '^URL: ' $(top_srcdir)/packages/rpm/rpm.spec >> "$@".tmp echo 'Requires:' >> "$@".tmp echo 'Libs: -L$${libdir} -ltcmalloc' >> "$@".tmp echo 'Libs.private: $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)' >> "$@".tmp diff --git a/third_party/tcmalloc/vendor/Makefile.in b/third_party/tcmalloc/vendor/Makefile.in index a7e27e9..f3aa67e 100644 --- a/third_party/tcmalloc/vendor/Makefile.in +++ b/third_party/tcmalloc/vendor/Makefile.in @@ -58,41 +58,42 @@ host_triplet = @host@ @GCC_TRUE@ -fno-builtin-memalign -fno-builtin-posix_memalign \ @GCC_TRUE@ -fno-builtin-valloc -fno-builtin-pvalloc +@HAVE_W_NO_UNUSED_RESULT_TRUE@am__append_3 = -Wno-unused-result # These are x86-specific, having to do with frame-pointers. In # particular, some x86_64 systems do not insert frame pointers by # default (all i386 systems that I know of, do. I don't know about # non-x86 chips). We need to tell perftools what to do about that. -@ENABLE_FRAME_POINTERS_TRUE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_3 = -fno-omit-frame-pointer -@ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_4 = -DNO_FRAME_POINTER -@MINGW_TRUE@am__append_5 = -Wl,-u__tcmalloc +@ENABLE_FRAME_POINTERS_TRUE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_4 = -fno-omit-frame-pointer +@ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_5 = -DNO_FRAME_POINTER +@MINGW_TRUE@am__append_6 = -Wl,-u__tcmalloc noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ - $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_24) + $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_28) bin_PROGRAMS = -@MINGW_TRUE@am__append_6 = libwindows.la libspinlock.la +@MINGW_TRUE@am__append_7 = libwindows.la libspinlock.la # We also need to tell mingw that sysinfo.cc needs shlwapi.lib. # (We do this via a #pragma for msvc, but need to do it here for mingw). -@MINGW_TRUE@am__append_7 = -lshlwapi -@MINGW_FALSE@am__append_8 = libspinlock.la -@WITH_STACK_TRACE_TRUE@am__append_9 = $(SG_STACKTRACE_INCLUDES) +@MINGW_TRUE@am__append_8 = -lshlwapi +@MINGW_FALSE@am__append_9 = libspinlock.la +@WITH_STACK_TRACE_TRUE@am__append_10 = $(SG_STACKTRACE_INCLUDES) ### Making the library -@WITH_STACK_TRACE_TRUE@am__append_10 = libstacktrace.la +@WITH_STACK_TRACE_TRUE@am__append_11 = libstacktrace.la ### Unittests -@WITH_STACK_TRACE_TRUE@am__append_11 = stacktrace_unittest +@WITH_STACK_TRACE_TRUE@am__append_12 = stacktrace_unittest ### Documentation -@WITH_STACK_TRACE_TRUE@am__append_12 = doc/pprof_remote_servers.html +@WITH_STACK_TRACE_TRUE@am__append_13 = doc/pprof_remote_servers.html # Let unittests find pprof if they need to run it -@WITH_STACK_TRACE_TRUE@am__append_13 = PPROF_PATH=$(top_srcdir)/src/pprof +@WITH_STACK_TRACE_TRUE@am__append_14 = PPROF_PATH=$(top_srcdir)/src/pprof # On MSVC, we need our own versions of addr2line and nm to work with pprof. # This is a slight abuse of WINDOWS_PROJECTS, but not much -@WITH_STACK_TRACE_TRUE@am__append_14 = \ +@WITH_STACK_TRACE_TRUE@am__append_15 = \ @WITH_STACK_TRACE_TRUE@ vsprojects/nm-pdb/nm-pdb.vcproj \ @WITH_STACK_TRACE_TRUE@ vsprojects/addr2line-pdb/addr2line-pdb.vcproj \ @WITH_STACK_TRACE_TRUE@ src/windows/nm-pdb.c \ @@ -104,41 +105,41 @@ bin_PROGRAMS = # libraries anyway (so can't be LD_PRELOADed) -- in fact, anybody who # chooses not to build shared libraries won't be able to run this test. # TODO(csilvers): figure out how to nix ".exe" or otherwise work under mingw -@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_15 = maybe_threads_unittest.sh$(EXEEXT) -@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_16 = $(maybe_threads_unittest_sh_SOURCES) -@MINGW_TRUE@am__append_17 = src/windows/port.h src/windows/port.cc -@MINGW_FALSE@am__append_18 = system_alloc_unittest +@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_16 = maybe_threads_unittest.sh$(EXEEXT) +@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_17 = $(maybe_threads_unittest_sh_SOURCES) +@MINGW_TRUE@am__append_18 = src/windows/port.h src/windows/port.cc +@MINGW_FALSE@am__append_19 = system_alloc_unittest # This doesn't work with static linkage, because libtcmalloc.a isn't # happy with C linkage (it misses the stdc++ library). Likewise with # mingw, which links foo.a even though it doesn't set ENABLE_STATIC. # TODO(csilvers): set enable_static=true in configure.ac:36? -@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_19 = malloc_extension_c_test +@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_20 = malloc_extension_c_test # -ansi here is just to help ensure the code is bog-standard C. -@ENABLE_STATIC_FALSE@@GCC_TRUE@@MINGW_FALSE@am__append_20 = -ansi -@MINGW_FALSE@am__append_21 = memalign_unittest +@ENABLE_STATIC_FALSE@@GCC_TRUE@@MINGW_FALSE@am__append_21 = -ansi +@MINGW_FALSE@@OSX_FALSE@am__append_22 = memalign_unittest ### ------- tcmalloc_minimal_debug (thread-caching malloc with debugallocation) # Like tcmalloc.cc, debugallocation.cc needs exceptions to fulfill its # API. Luckily, we can reuse everything else from tcmalloc_minimal. -@WITH_DEBUGALLOC_TRUE@am__append_22 = libtcmalloc_minimal_debug.la @WITH_DEBUGALLOC_TRUE@am__append_23 = libtcmalloc_minimal_debug.la +@WITH_DEBUGALLOC_TRUE@am__append_24 = libtcmalloc_minimal_debug.la ### Unittests -@WITH_DEBUGALLOC_TRUE@am__append_24 = tcmalloc_minimal_debug_unittest \ -@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test \ -@WITH_DEBUGALLOC_TRUE@ memalign_debug_unittest \ -@WITH_DEBUGALLOC_TRUE@ realloc_debug_unittest +@WITH_DEBUGALLOC_TRUE@am__append_25 = tcmalloc_minimal_debug_unittest \ +@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am__append_26 = memalign_debug_unittest +@WITH_DEBUGALLOC_TRUE@am__append_27 = realloc_debug_unittest # debugallocation_test checks that we print a proper stacktrace when # debug-allocs fail, so we can't run it if we don't have stacktrace info. -@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_25 = debugallocation_test.sh$(EXEEXT) -@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_26 = $(debugallocation_test_sh_SOURCES) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_28 = debugallocation_test.sh$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_29 = $(debugallocation_test_sh_SOURCES) # This is the sub-program used by debugallocation_test.sh -@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_27 = debugallocation_test -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_28 = $(SG_TCMALLOC_INCLUDES) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_30 = debugallocation_test +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_31 = $(SG_TCMALLOC_INCLUDES) ### Making the library @@ -146,21 +147,17 @@ bin_PROGRAMS = # for all files in this library -- except tcmalloc.cc which needs them # to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need # to separate into two libraries. -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_29 = libtcmalloc_internal.la -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_30 = libtcmalloc.la -@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_31 = $(HEAP_CHECKER_SOURCES) -@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_32 = -DNO_HEAP_CHECK -@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_33 = -DNO_HEAP_CHECK -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_34 = libtcmalloc.la +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_32 = libtcmalloc_internal.la +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_33 = libtcmalloc.la +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_34 = $(HEAP_CHECKER_SOURCES) +@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_35 = -DNO_HEAP_CHECK +@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_36 = -DNO_HEAP_CHECK +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_37 = libtcmalloc.la ### Unittests - -# This makes sure it's safe to link in both tcmalloc and -# tcmalloc_minimal. (One would never do this on purpose, but perhaps -# by accident...) When we can compile libprofiler, we also link it in -# to make sure that works too. -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_35 = tcmalloc_unittest \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_both_unittest \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_38 = tcmalloc_unittest +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_39 = tcmalloc_both_unittest +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_40 = \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_unittest \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ raw_printer_test \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_test \ @@ -170,74 +167,74 @@ bin_PROGRAMS = # on, which it's not by default. Use the "standard" value of 2^19. # These unittests often need to run binaries. They're in the current dir -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_36 = TCMALLOC_SAMPLE_PARAMETER=524288 \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_41 = TCMALLOC_SAMPLE_PARAMETER=524288 \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ BINDIR=. \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ TMPDIR=/tmp/perftools -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_37 = vsprojects/sampler_test/sampler_test.vcproj -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_38 = $(sampling_test_sh_SOURCES) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_42 = vsprojects/sampler_test/sampler_test.vcproj +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_43 = $(sampling_test_sh_SOURCES) # This is the sub-program used by sampling_test.sh # The -g is so pprof can get symbol information. -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_39 = sampling_test -@WITH_HEAP_PROFILER_TRUE@am__append_40 = heap-profiler_unittest.sh$(EXEEXT) -@WITH_HEAP_PROFILER_TRUE@am__append_41 = $(heap_profiler_unittest_sh_SOURCES) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_44 = sampling_test +@WITH_HEAP_PROFILER_TRUE@am__append_45 = heap-profiler_unittest.sh$(EXEEXT) +@WITH_HEAP_PROFILER_TRUE@am__append_46 = $(heap_profiler_unittest_sh_SOURCES) # These are sub-programs used by heap-profiler_unittest.sh -@WITH_HEAP_PROFILER_TRUE@am__append_42 = heap-profiler_unittest -@WITH_HEAP_CHECKER_TRUE@am__append_43 = \ +@WITH_HEAP_PROFILER_TRUE@am__append_47 = heap-profiler_unittest +@WITH_HEAP_CHECKER_TRUE@am__append_48 = \ @WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest.sh$(EXEEXT) \ @WITH_HEAP_CHECKER_TRUE@ heap-checker-death_unittest.sh$(EXEEXT) -@WITH_HEAP_CHECKER_TRUE@am__append_44 = \ +@WITH_HEAP_CHECKER_TRUE@am__append_49 = \ @WITH_HEAP_CHECKER_TRUE@ $(heap_checker_unittest_sh_SOURCES) \ @WITH_HEAP_CHECKER_TRUE@ $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES) # These are sub-programs used by heap-checker_unittest.sh -@WITH_HEAP_CHECKER_TRUE@am__append_45 = heap-checker_unittest +@WITH_HEAP_CHECKER_TRUE@am__append_50 = heap-checker_unittest ### Documentation (above and beyond tcmalloc_minimal documentation) -@WITH_HEAP_PROFILER_TRUE@am__append_46 = doc/heapprofile.html doc/heap-example1.png -@WITH_HEAP_CHECKER_TRUE@am__append_47 = doc/heap_checker.html +@WITH_HEAP_PROFILER_TRUE@am__append_51 = doc/heapprofile.html doc/heap-example1.png +@WITH_HEAP_CHECKER_TRUE@am__append_52 = doc/heap_checker.html ### ------- tcmalloc with debugallocation -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_48 = libtcmalloc_debug.la -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_49 = libtcmalloc_debug.la +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_53 = libtcmalloc_debug.la +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_54 = libtcmalloc_debug.la ### Unittests -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_50 = tcmalloc_debug_unittest \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_55 = tcmalloc_debug_unittest \ @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_debug_test \ @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test.sh$(EXEEXT) # This is the sub-program using by sampling_debug_test.sh # The -g is so pprof can get symbol information. -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_51 = sampling_debug_test -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_52 = heap-profiler_debug_unittest.sh$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_56 = sampling_debug_test +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_57 = heap-profiler_debug_unittest.sh$(EXEEXT) # These are sub-programs used by heap-profiler_debug_unittest.sh -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_53 = heap-profiler_debug_unittest -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_54 = heap-checker_debug_unittest.sh$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_58 = heap-profiler_debug_unittest +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_59 = heap-checker_debug_unittest.sh$(EXEEXT) # These are sub-programs used by heap-checker_debug_unittest.sh -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_55 = heap-checker_debug_unittest -@WITH_CPU_PROFILER_TRUE@am__append_56 = $(SG_CPU_PROFILER_INCLUDES) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_60 = heap-checker_debug_unittest +@WITH_CPU_PROFILER_TRUE@am__append_61 = $(SG_CPU_PROFILER_INCLUDES) ### Making the library -@WITH_CPU_PROFILER_TRUE@am__append_57 = libprofiler.la +@WITH_CPU_PROFILER_TRUE@am__append_62 = libprofiler.la ### Unittests -@WITH_CPU_PROFILER_TRUE@am__append_58 = getpc_test \ +@WITH_CPU_PROFILER_TRUE@am__append_63 = getpc_test \ @WITH_CPU_PROFILER_TRUE@ profiledata_unittest \ @WITH_CPU_PROFILER_TRUE@ profile_handler_unittest \ @WITH_CPU_PROFILER_TRUE@ profiler_unittest.sh$(EXEEXT) -@WITH_CPU_PROFILER_TRUE@am__append_59 = $(profiler_unittest_sh_SOURCES) +@WITH_CPU_PROFILER_TRUE@am__append_64 = $(profiler_unittest_sh_SOURCES) # These are sub-programs used by profiler_unittest.sh -@WITH_CPU_PROFILER_TRUE@am__append_60 = profiler1_unittest profiler2_unittest profiler3_unittest \ +@WITH_CPU_PROFILER_TRUE@am__append_65 = profiler1_unittest profiler2_unittest profiler3_unittest \ @WITH_CPU_PROFILER_TRUE@ profiler4_unittest @WITH_CPU_PROFILER_FALSE@profiler2_unittest_DEPENDENCIES = ### Documentation -@WITH_CPU_PROFILER_TRUE@am__append_61 = doc/cpuprofile.html \ +@WITH_CPU_PROFILER_TRUE@am__append_66 = doc/cpuprofile.html \ @WITH_CPU_PROFILER_TRUE@ doc/cpuprofile-fileformat.html \ @WITH_CPU_PROFILER_TRUE@ doc/pprof-test-big.gif \ @WITH_CPU_PROFILER_TRUE@ doc/pprof-test.gif \ @@ -252,9 +249,9 @@ bin_PROGRAMS = # works fine for .so files, it does not for .a files. The easiest way # around this -- and I've tried a bunch of the hard ways -- is to just # to create another set of libraries that has both functionality in it. -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_62 = libtcmalloc_and_profiler.la -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_63 = tcmalloc_and_profiler_unittest -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_64 = libtcmalloc_and_profiler.la +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_67 = libtcmalloc_and_profiler.la +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_68 = tcmalloc_and_profiler_unittest +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_69 = libtcmalloc_and_profiler.la DIST_COMMON = README $(am__configure_deps) $(am__dist_doc_DATA_DIST) \ $(am__googleinclude_HEADERS_DIST) $(dist_man_MANS) \ $(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ @@ -361,15 +358,18 @@ libspinlock_la_OBJECTS = $(am_libspinlock_la_OBJECTS) @WITH_STACK_TRACE_TRUE@ $(am__DEPENDENCIES_1) \ @WITH_STACK_TRACE_TRUE@ $(am__DEPENDENCIES_2) am__libstacktrace_la_SOURCES_DIST = src/stacktrace.cc \ - src/base/vdso_support.cc src/stacktrace_config.h \ - src/stacktrace_generic-inl.h src/stacktrace_libunwind-inl.h \ + src/base/elf_mem_image.cc src/base/vdso_support.cc \ + src/stacktrace_config.h src/stacktrace_generic-inl.h \ + src/stacktrace_libunwind-inl.h src/stacktrace_nacl-inl.h \ src/stacktrace_powerpc-inl.h src/stacktrace_x86_64-inl.h \ src/stacktrace_x86-inl.h src/stacktrace_win32-inl.h \ - src/base/vdso_support.h src/google/stacktrace.h + src/base/elf_mem_image.h src/base/vdso_support.h \ + src/google/stacktrace.h @WITH_STACK_TRACE_TRUE@am__objects_4 = $(am__objects_1) \ @WITH_STACK_TRACE_TRUE@ $(am__objects_1) @WITH_STACK_TRACE_TRUE@am_libstacktrace_la_OBJECTS = stacktrace.lo \ -@WITH_STACK_TRACE_TRUE@ vdso_support.lo $(am__objects_4) +@WITH_STACK_TRACE_TRUE@ elf_mem_image.lo vdso_support.lo \ +@WITH_STACK_TRACE_TRUE@ $(am__objects_4) libstacktrace_la_OBJECTS = $(am_libstacktrace_la_OBJECTS) @WITH_STACK_TRACE_TRUE@am_libstacktrace_la_rpath = libsysinfo_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ @@ -394,22 +394,26 @@ am__libtcmalloc_la_SOURCES_DIST = src/tcmalloc.cc src/common.h \ src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ - src/linked_list.h src/page_heap.h src/page_heap_allocator.h \ - src/span.h src/static_vars.h src/symbolize.h \ - src/thread_cache.h src/stack_trace_table.h \ - src/base/thread_annotations.h src/malloc_hook-inl.h \ - src/maybe_threads.h src/base/logging.h \ - src/base/dynamic_annotations.h src/third_party/valgrind.h \ - src/addressmap-inl.h src/raw_printer.h src/base/elfcore.h \ - src/base/googleinit.h src/base/linux_syscall_support.h \ - src/base/linuxthreads.h src/base/stl_allocator.h \ - src/base/sysinfo.h src/base/thread_lister.h \ - src/heap-profile-table.h src/google/malloc_hook.h \ - src/google/malloc_hook_c.h src/google/malloc_extension.h \ - src/google/malloc_extension_c.h src/google/stacktrace.h \ - src/google/heap-profiler.h src/google/heap-checker.h \ - src/base/thread_lister.c src/base/linuxthreads.cc \ - src/heap-checker.cc src/heap-checker-bcad.cc + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/maybe_threads.h \ + src/base/logging.h src/base/dynamic_annotations.h \ + src/third_party/valgrind.h src/addressmap-inl.h \ + src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ + src/base/linux_syscall_support.h src/base/linuxthreads.h \ + src/base/stl_allocator.h src/base/sysinfo.h \ + src/base/thread_lister.h src/heap-profile-table.h \ + src/google/malloc_hook.h src/google/malloc_hook_c.h \ + src/google/malloc_extension.h src/google/malloc_extension_c.h \ + src/google/stacktrace.h src/google/heap-profiler.h \ + src/google/heap-checker.h src/base/thread_lister.c \ + src/base/linuxthreads.cc src/heap-checker.cc \ + src/heap-checker-bcad.cc @MINGW_FALSE@am__objects_5 = libtcmalloc_la-tcmalloc.lo am__objects_6 = $(am__objects_1) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_7 = $(am__objects_6) \ @@ -448,22 +452,26 @@ am__libtcmalloc_and_profiler_la_SOURCES_DIST = src/tcmalloc.cc \ src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ - src/linked_list.h src/page_heap.h src/page_heap_allocator.h \ - src/span.h src/static_vars.h src/symbolize.h \ - src/thread_cache.h src/stack_trace_table.h \ - src/base/thread_annotations.h src/malloc_hook-inl.h \ - src/maybe_threads.h src/base/logging.h \ - src/base/dynamic_annotations.h src/third_party/valgrind.h \ - src/addressmap-inl.h src/raw_printer.h src/base/elfcore.h \ - src/base/googleinit.h src/base/linux_syscall_support.h \ - src/base/linuxthreads.h src/base/stl_allocator.h \ - src/base/sysinfo.h src/base/thread_lister.h \ - src/heap-profile-table.h src/google/malloc_hook.h \ - src/google/malloc_hook_c.h src/google/malloc_extension.h \ - src/google/malloc_extension_c.h src/google/stacktrace.h \ - src/google/heap-profiler.h src/google/heap-checker.h \ - src/base/thread_lister.c src/base/linuxthreads.cc \ - src/heap-checker.cc src/heap-checker-bcad.cc src/profiler.cc \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/maybe_threads.h \ + src/base/logging.h src/base/dynamic_annotations.h \ + src/third_party/valgrind.h src/addressmap-inl.h \ + src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ + src/base/linux_syscall_support.h src/base/linuxthreads.h \ + src/base/stl_allocator.h src/base/sysinfo.h \ + src/base/thread_lister.h src/heap-profile-table.h \ + src/google/malloc_hook.h src/google/malloc_hook_c.h \ + src/google/malloc_extension.h src/google/malloc_extension_c.h \ + src/google/stacktrace.h src/google/heap-profiler.h \ + src/google/heap-checker.h src/base/thread_lister.c \ + src/base/linuxthreads.cc src/heap-checker.cc \ + src/heap-checker-bcad.cc src/profiler.cc \ src/profile-handler.cc src/profiledata.cc src/profiledata.h \ src/profile-handler.h src/getpc.h src/base/simple_mutex.h \ src/google/profiler.h @@ -505,20 +513,24 @@ am__libtcmalloc_debug_la_SOURCES_DIST = src/debugallocation.cc \ src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ - src/linked_list.h src/page_heap.h src/page_heap_allocator.h \ - src/span.h src/static_vars.h src/symbolize.h \ - src/thread_cache.h src/stack_trace_table.h \ - src/base/thread_annotations.h src/malloc_hook-inl.h \ - src/maybe_threads.h src/base/logging.h \ - src/base/dynamic_annotations.h src/third_party/valgrind.h \ - src/addressmap-inl.h src/raw_printer.h src/base/elfcore.h \ - src/base/googleinit.h src/base/linux_syscall_support.h \ - src/base/linuxthreads.h src/base/stl_allocator.h \ - src/base/sysinfo.h src/base/thread_lister.h \ - src/heap-profile-table.h src/google/malloc_hook.h \ - src/google/malloc_hook_c.h src/google/malloc_extension.h \ - src/google/malloc_extension_c.h src/google/stacktrace.h \ - src/google/heap-profiler.h src/google/heap-checker.h + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/maybe_threads.h \ + src/base/logging.h src/base/dynamic_annotations.h \ + src/third_party/valgrind.h src/addressmap-inl.h \ + src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ + src/base/linux_syscall_support.h src/base/linuxthreads.h \ + src/base/stl_allocator.h src/base/sysinfo.h \ + src/base/thread_lister.h src/heap-profile-table.h \ + src/google/malloc_hook.h src/google/malloc_hook_c.h \ + src/google/malloc_extension.h src/google/malloc_extension_c.h \ + src/google/stacktrace.h src/google/heap-profiler.h \ + src/google/heap-checker.h @WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_17 = thread_lister.lo \ @WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_debug_la-linuxthreads.lo \ @WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_debug_la-heap-checker.lo \ @@ -552,23 +564,26 @@ am__libtcmalloc_internal_la_SOURCES_DIST = src/common.cc \ src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ - src/linked_list.h src/page_heap.h src/page_heap_allocator.h \ - src/span.h src/static_vars.h src/symbolize.h \ - src/thread_cache.h src/stack_trace_table.h \ - src/base/thread_annotations.h src/malloc_hook-inl.h \ - src/maybe_threads.h src/google/malloc_hook.h \ - src/google/malloc_hook_c.h src/google/malloc_extension.h \ - src/google/malloc_extension_c.h src/google/stacktrace.h \ - src/base/logging.h src/base/dynamic_annotations.h \ - src/third_party/valgrind.h src/addressmap-inl.h \ - src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ - src/base/linux_syscall_support.h src/base/linuxthreads.h \ - src/base/stl_allocator.h src/base/sysinfo.h \ - src/base/thread_lister.h src/heap-profile-table.h \ - src/google/heap-profiler.h src/google/heap-checker.h \ - src/base/low_level_alloc.cc src/heap-profile-table.cc \ - src/heap-profiler.cc src/raw_printer.cc \ - src/memory_region_map.cc + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/maybe_threads.h \ + src/google/malloc_hook.h src/google/malloc_hook_c.h \ + src/google/malloc_extension.h src/google/malloc_extension_c.h \ + src/google/stacktrace.h src/base/logging.h \ + src/base/dynamic_annotations.h src/third_party/valgrind.h \ + src/addressmap-inl.h src/raw_printer.h src/base/elfcore.h \ + src/base/googleinit.h src/base/linux_syscall_support.h \ + src/base/linuxthreads.h src/base/stl_allocator.h \ + src/base/sysinfo.h src/base/thread_lister.h \ + src/heap-profile-table.h src/google/heap-profiler.h \ + src/google/heap-checker.h src/base/low_level_alloc.cc \ + src/heap-profile-table.cc src/heap-profiler.cc \ + src/raw_printer.cc src/memory_region_map.cc @MINGW_FALSE@am__objects_18 = libtcmalloc_internal_la-system-alloc.lo @MINGW_FALSE@am__objects_19 = \ @MINGW_FALSE@ libtcmalloc_internal_la-maybe_threads.lo @@ -615,13 +630,17 @@ am__libtcmalloc_minimal_la_SOURCES_DIST = src/tcmalloc.cc src/common.h \ src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ - src/linked_list.h src/page_heap.h src/page_heap_allocator.h \ - src/span.h src/static_vars.h src/symbolize.h \ - src/thread_cache.h src/stack_trace_table.h \ - src/base/thread_annotations.h src/malloc_hook-inl.h \ - src/maybe_threads.h src/google/malloc_hook.h \ - src/google/malloc_hook_c.h src/google/malloc_extension.h \ - src/google/malloc_extension_c.h src/google/stacktrace.h + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/maybe_threads.h \ + src/google/malloc_hook.h src/google/malloc_hook_c.h \ + src/google/malloc_extension.h src/google/malloc_extension_c.h \ + src/google/stacktrace.h @MINGW_FALSE@am__objects_22 = libtcmalloc_minimal_la-tcmalloc.lo am_libtcmalloc_minimal_la_OBJECTS = $(am__objects_22) \ $(am__objects_20) @@ -645,13 +664,17 @@ am__libtcmalloc_minimal_debug_la_SOURCES_DIST = \ src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ - src/linked_list.h src/page_heap.h src/page_heap_allocator.h \ - src/span.h src/static_vars.h src/symbolize.h \ - src/thread_cache.h src/stack_trace_table.h \ - src/base/thread_annotations.h src/malloc_hook-inl.h \ - src/maybe_threads.h src/google/malloc_hook.h \ - src/google/malloc_hook_c.h src/google/malloc_extension.h \ - src/google/malloc_extension_c.h src/google/stacktrace.h + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/maybe_threads.h \ + src/google/malloc_hook.h src/google/malloc_hook_c.h \ + src/google/malloc_extension.h src/google/malloc_extension_c.h \ + src/google/stacktrace.h @WITH_DEBUGALLOC_TRUE@am_libtcmalloc_minimal_debug_la_OBJECTS = libtcmalloc_minimal_debug_la-debugallocation.lo \ @WITH_DEBUGALLOC_TRUE@ $(am__objects_20) libtcmalloc_minimal_debug_la_OBJECTS = \ @@ -680,13 +703,17 @@ am__libtcmalloc_minimal_internal_la_SOURCES_DIST = src/common.cc \ src/base/atomicops-internals-arm-v6plus.h src/tcmalloc_guard.h \ src/base/commandlineflags.h src/base/basictypes.h \ src/pagemap.h src/sampler.h src/central_freelist.h \ - src/linked_list.h src/page_heap.h src/page_heap_allocator.h \ - src/span.h src/static_vars.h src/symbolize.h \ - src/thread_cache.h src/stack_trace_table.h \ - src/base/thread_annotations.h src/malloc_hook-inl.h \ - src/maybe_threads.h src/google/malloc_hook.h \ - src/google/malloc_hook_c.h src/google/malloc_extension.h \ - src/google/malloc_extension_c.h src/google/stacktrace.h + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/maybe_threads.h \ + src/google/malloc_hook.h src/google/malloc_hook_c.h \ + src/google/malloc_extension.h src/google/malloc_extension_c.h \ + src/google/stacktrace.h @MINGW_FALSE@am__objects_23 = \ @MINGW_FALSE@ libtcmalloc_minimal_internal_la-system-alloc.lo @MINGW_FALSE@am__objects_24 = \ @@ -742,34 +769,34 @@ binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) @ENABLE_STATIC_FALSE@@MINGW_FALSE@am__EXEEXT_10 = maybe_threads_unittest.sh$(EXEEXT) @MINGW_FALSE@am__EXEEXT_11 = system_alloc_unittest$(EXEEXT) @ENABLE_STATIC_FALSE@@MINGW_FALSE@am__EXEEXT_12 = malloc_extension_c_test$(EXEEXT) -@MINGW_FALSE@am__EXEEXT_13 = memalign_unittest$(EXEEXT) +@MINGW_FALSE@@OSX_FALSE@am__EXEEXT_13 = memalign_unittest$(EXEEXT) @WITH_DEBUGALLOC_TRUE@am__EXEEXT_14 = tcmalloc_minimal_debug_unittest$(EXEEXT) \ -@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test$(EXEEXT) \ -@WITH_DEBUGALLOC_TRUE@ memalign_debug_unittest$(EXEEXT) \ -@WITH_DEBUGALLOC_TRUE@ realloc_debug_unittest$(EXEEXT) -@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__EXEEXT_15 = debugallocation_test.sh$(EXEEXT) -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_16 = tcmalloc_unittest$(EXEEXT) \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_both_unittest$(EXEEXT) \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_unittest$(EXEEXT) \ +@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test$(EXEEXT) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am__EXEEXT_15 = memalign_debug_unittest$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@am__EXEEXT_16 = realloc_debug_unittest$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__EXEEXT_17 = debugallocation_test.sh$(EXEEXT) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_18 = tcmalloc_unittest$(EXEEXT) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_19 = tcmalloc_both_unittest$(EXEEXT) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_20 = tcmalloc_large_unittest$(EXEEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ raw_printer_test$(EXEEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_test$(EXEEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test.sh$(EXEEXT) -@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_17 = \ +@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_21 = \ @WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest.sh$(EXEEXT) -@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_18 = \ +@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_22 = \ @WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest.sh$(EXEEXT) \ @WITH_HEAP_CHECKER_TRUE@ heap-checker-death_unittest.sh$(EXEEXT) -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_19 = tcmalloc_debug_unittest$(EXEEXT) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_23 = tcmalloc_debug_unittest$(EXEEXT) \ @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_debug_test$(EXEEXT) \ @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test.sh$(EXEEXT) -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_20 = heap-profiler_debug_unittest.sh$(EXEEXT) -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_21 = heap-checker_debug_unittest.sh$(EXEEXT) -@WITH_CPU_PROFILER_TRUE@am__EXEEXT_22 = getpc_test$(EXEEXT) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_24 = heap-profiler_debug_unittest.sh$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_25 = heap-checker_debug_unittest.sh$(EXEEXT) +@WITH_CPU_PROFILER_TRUE@am__EXEEXT_26 = getpc_test$(EXEEXT) \ @WITH_CPU_PROFILER_TRUE@ profiledata_unittest$(EXEEXT) \ @WITH_CPU_PROFILER_TRUE@ profile_handler_unittest$(EXEEXT) \ @WITH_CPU_PROFILER_TRUE@ profiler_unittest.sh$(EXEEXT) -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_23 = tcmalloc_and_profiler_unittest$(EXEEXT) -am__EXEEXT_24 = low_level_alloc_unittest$(EXEEXT) \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_27 = tcmalloc_and_profiler_unittest$(EXEEXT) +am__EXEEXT_28 = low_level_alloc_unittest$(EXEEXT) \ atomicops_unittest$(EXEEXT) $(am__EXEEXT_9) \ tcmalloc_minimal_unittest$(EXEEXT) \ tcmalloc_minimal_large_unittest$(EXEEXT) $(am__EXEEXT_10) \ @@ -784,7 +811,9 @@ am__EXEEXT_24 = low_level_alloc_unittest$(EXEEXT) \ thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_14) \ $(am__EXEEXT_15) $(am__EXEEXT_16) $(am__EXEEXT_17) \ $(am__EXEEXT_18) $(am__EXEEXT_19) $(am__EXEEXT_20) \ - $(am__EXEEXT_21) $(am__EXEEXT_22) $(am__EXEEXT_23) + $(am__EXEEXT_21) $(am__EXEEXT_22) $(am__EXEEXT_23) \ + $(am__EXEEXT_24) $(am__EXEEXT_25) $(am__EXEEXT_26) \ + $(am__EXEEXT_27) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am__addressmap_unittest_SOURCES_DIST = \ src/tests/addressmap_unittest.cc src/addressmap-inl.h \ @@ -913,7 +942,8 @@ am__low_level_alloc_unittest_SOURCES_DIST = \ src/maybe_threads.cc src/tests/low_level_alloc_unittest.cc \ src/base/low_level_alloc.h src/base/basictypes.h \ src/google/malloc_hook.h src/google/malloc_hook_c.h \ - src/malloc_hook-inl.h src/base/spinlock.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/base/spinlock.h \ src/base/spinlock_internal.h src/base/atomicops.h \ src/base/atomicops-internals-macosx.h \ src/base/atomicops-internals-linuxppc.h \ @@ -926,13 +956,15 @@ am__low_level_alloc_unittest_SOURCES_DIST = \ src/base/atomicops-internals-arm-v6plus.h src/base/logging.h \ src/base/commandlineflags.h src/base/dynamic_annotations.h \ src/third_party/valgrind.h -am__objects_29 = $(am__objects_1) $(am__objects_1) +@MINGW_FALSE@am__objects_29 = \ +@MINGW_FALSE@ low_level_alloc_unittest-maybe_threads.$(OBJEXT) +am__objects_30 = $(am__objects_1) $(am__objects_1) am_low_level_alloc_unittest_OBJECTS = \ low_level_alloc_unittest-low_level_alloc.$(OBJEXT) \ low_level_alloc_unittest-malloc_hook.$(OBJEXT) \ - low_level_alloc_unittest-maybe_threads.$(OBJEXT) \ + $(am__objects_29) \ low_level_alloc_unittest-low_level_alloc_unittest.$(OBJEXT) \ - $(am__objects_29) + $(am__objects_30) low_level_alloc_unittest_OBJECTS = \ $(am_low_level_alloc_unittest_OBJECTS) low_level_alloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2) @@ -949,10 +981,10 @@ am__malloc_extension_debug_test_SOURCES_DIST = \ src/tests/malloc_extension_test.cc src/config_for_unittests.h \ src/base/logging.h src/google/malloc_extension.h \ src/google/malloc_extension_c.h -am__objects_30 = \ +am__objects_31 = \ malloc_extension_debug_test-malloc_extension_test.$(OBJEXT) @WITH_DEBUGALLOC_TRUE@am_malloc_extension_debug_test_OBJECTS = \ -@WITH_DEBUGALLOC_TRUE@ $(am__objects_30) +@WITH_DEBUGALLOC_TRUE@ $(am__objects_31) malloc_extension_debug_test_OBJECTS = \ $(am_malloc_extension_debug_test_OBJECTS) @WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_DEPENDENCIES = \ @@ -985,24 +1017,22 @@ am__memalign_debug_unittest_SOURCES_DIST = \ src/tests/memalign_unittest.cc src/tcmalloc.h \ src/config_for_unittests.h src/tests/testutil.h \ src/tests/testutil.cc -@MINGW_FALSE@am__objects_31 = memalign_debug_unittest-memalign_unittest.$(OBJEXT) \ -@MINGW_FALSE@ memalign_debug_unittest-testutil.$(OBJEXT) -@WITH_DEBUGALLOC_TRUE@am_memalign_debug_unittest_OBJECTS = \ -@WITH_DEBUGALLOC_TRUE@ $(am__objects_31) +@MINGW_FALSE@@OSX_FALSE@am__objects_32 = memalign_debug_unittest-memalign_unittest.$(OBJEXT) \ +@MINGW_FALSE@@OSX_FALSE@ memalign_debug_unittest-testutil.$(OBJEXT) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am_memalign_debug_unittest_OBJECTS = $(am__objects_32) memalign_debug_unittest_OBJECTS = \ $(am_memalign_debug_unittest_OBJECTS) -@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_DEPENDENCIES = \ -@WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \ -@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_DEPENDENCIES = libtcmalloc_minimal_debug.la \ +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1) am__memalign_unittest_SOURCES_DIST = src/tests/memalign_unittest.cc \ src/tcmalloc.h src/config_for_unittests.h src/tests/testutil.h \ src/tests/testutil.cc -@MINGW_FALSE@am_memalign_unittest_OBJECTS = \ -@MINGW_FALSE@ memalign_unittest-memalign_unittest.$(OBJEXT) \ -@MINGW_FALSE@ memalign_unittest-testutil.$(OBJEXT) +@MINGW_FALSE@@OSX_FALSE@am_memalign_unittest_OBJECTS = memalign_unittest-memalign_unittest.$(OBJEXT) \ +@MINGW_FALSE@@OSX_FALSE@ memalign_unittest-testutil.$(OBJEXT) memalign_unittest_OBJECTS = $(am_memalign_unittest_OBJECTS) -@MINGW_FALSE@memalign_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \ -@MINGW_FALSE@ $(am__DEPENDENCIES_1) +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_DEPENDENCIES = \ +@MINGW_FALSE@@OSX_FALSE@ $(am__DEPENDENCIES_5) \ +@MINGW_FALSE@@OSX_FALSE@ $(am__DEPENDENCIES_1) am_packed_cache_test_OBJECTS = \ packed_cache_test-packed-cache_test.$(OBJEXT) packed_cache_test_OBJECTS = $(am_packed_cache_test_OBJECTS) @@ -1039,31 +1069,31 @@ profiledata_unittest_OBJECTS = $(am_profiledata_unittest_OBJECTS) am__profiler1_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \ src/tests/testutil.h src/tests/testutil.cc \ src/config_for_unittests.h src/google/profiler.h -@WITH_CPU_PROFILER_TRUE@am__objects_32 = profiler1_unittest-profiler_unittest.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@am__objects_33 = profiler1_unittest-profiler_unittest.$(OBJEXT) \ @WITH_CPU_PROFILER_TRUE@ profiler1_unittest-testutil.$(OBJEXT) \ @WITH_CPU_PROFILER_TRUE@ $(am__objects_1) @WITH_CPU_PROFILER_TRUE@am_profiler1_unittest_OBJECTS = \ -@WITH_CPU_PROFILER_TRUE@ $(am__objects_32) +@WITH_CPU_PROFILER_TRUE@ $(am__objects_33) profiler1_unittest_OBJECTS = $(am_profiler1_unittest_OBJECTS) @WITH_CPU_PROFILER_TRUE@profiler1_unittest_DEPENDENCIES = \ @WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_7) am__profiler2_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \ src/tests/testutil.h src/tests/testutil.cc \ src/config_for_unittests.h src/google/profiler.h -@WITH_CPU_PROFILER_TRUE@am__objects_33 = profiler2_unittest-profiler_unittest.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@am__objects_34 = profiler2_unittest-profiler_unittest.$(OBJEXT) \ @WITH_CPU_PROFILER_TRUE@ profiler2_unittest-testutil.$(OBJEXT) \ @WITH_CPU_PROFILER_TRUE@ $(am__objects_1) @WITH_CPU_PROFILER_TRUE@am_profiler2_unittest_OBJECTS = \ -@WITH_CPU_PROFILER_TRUE@ $(am__objects_33) +@WITH_CPU_PROFILER_TRUE@ $(am__objects_34) profiler2_unittest_OBJECTS = $(am_profiler2_unittest_OBJECTS) am__profiler3_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \ src/tests/testutil.h src/tests/testutil.cc \ src/config_for_unittests.h src/google/profiler.h -@WITH_CPU_PROFILER_TRUE@am__objects_34 = profiler3_unittest-profiler_unittest.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@am__objects_35 = profiler3_unittest-profiler_unittest.$(OBJEXT) \ @WITH_CPU_PROFILER_TRUE@ profiler3_unittest-testutil.$(OBJEXT) \ @WITH_CPU_PROFILER_TRUE@ $(am__objects_1) @WITH_CPU_PROFILER_TRUE@am_profiler3_unittest_OBJECTS = \ -@WITH_CPU_PROFILER_TRUE@ $(am__objects_34) +@WITH_CPU_PROFILER_TRUE@ $(am__objects_35) profiler3_unittest_OBJECTS = $(am_profiler3_unittest_OBJECTS) @WITH_CPU_PROFILER_TRUE@profiler3_unittest_DEPENDENCIES = \ @WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_7) \ @@ -1071,11 +1101,11 @@ profiler3_unittest_OBJECTS = $(am_profiler3_unittest_OBJECTS) am__profiler4_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \ src/tests/testutil.h src/tests/testutil.cc \ src/config_for_unittests.h src/google/profiler.h -@WITH_CPU_PROFILER_TRUE@am__objects_35 = profiler4_unittest-profiler_unittest.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@am__objects_36 = profiler4_unittest-profiler_unittest.$(OBJEXT) \ @WITH_CPU_PROFILER_TRUE@ profiler4_unittest-testutil.$(OBJEXT) \ @WITH_CPU_PROFILER_TRUE@ $(am__objects_1) @WITH_CPU_PROFILER_TRUE@am_profiler4_unittest_OBJECTS = \ -@WITH_CPU_PROFILER_TRUE@ $(am__objects_35) +@WITH_CPU_PROFILER_TRUE@ $(am__objects_36) profiler4_unittest_OBJECTS = $(am_profiler4_unittest_OBJECTS) am__profiler_unittest_sh_SOURCES_DIST = \ src/tests/profiler_unittest.sh @@ -1091,9 +1121,9 @@ raw_printer_test_OBJECTS = $(am_raw_printer_test_OBJECTS) am__realloc_debug_unittest_SOURCES_DIST = \ src/tests/realloc_unittest.cc src/config_for_unittests.h \ src/base/logging.h -am__objects_36 = realloc_debug_unittest-realloc_unittest.$(OBJEXT) +am__objects_37 = realloc_debug_unittest-realloc_unittest.$(OBJEXT) @WITH_DEBUGALLOC_TRUE@am_realloc_debug_unittest_OBJECTS = \ -@WITH_DEBUGALLOC_TRUE@ $(am__objects_36) +@WITH_DEBUGALLOC_TRUE@ $(am__objects_37) realloc_debug_unittest_OBJECTS = $(am_realloc_debug_unittest_OBJECTS) @WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_DEPENDENCIES = \ @WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \ @@ -1105,8 +1135,8 @@ realloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \ $(am__DEPENDENCIES_1) am__sampler_debug_test_SOURCES_DIST = src/tests/sampler_test.cc \ src/config_for_unittests.h -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_37 = sampler_debug_test-sampler_test.$(OBJEXT) -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampler_debug_test_OBJECTS = $(am__objects_37) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_38 = sampler_debug_test-sampler_test.$(OBJEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampler_debug_test_OBJECTS = $(am__objects_38) sampler_debug_test_OBJECTS = $(am_sampler_debug_test_OBJECTS) @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_DEPENDENCIES = libtcmalloc_debug.la \ @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) @@ -1120,9 +1150,9 @@ sampler_test_OBJECTS = $(am_sampler_test_OBJECTS) am__sampling_debug_test_SOURCES_DIST = src/tests/sampling_test.cc \ src/config_for_unittests.h src/base/logging.h \ src/google/malloc_extension.h -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_38 = sampling_debug_test-sampling_test.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_39 = sampling_debug_test-sampling_test.$(OBJEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampling_debug_test_OBJECTS = $(am__objects_38) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampling_debug_test_OBJECTS = $(am__objects_39) sampling_debug_test_OBJECTS = $(am_sampling_debug_test_OBJECTS) @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_DEPENDENCIES = libtcmalloc_debug.la \ @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) @@ -1152,16 +1182,17 @@ am__stacktrace_unittest_SOURCES_DIST = \ src/tests/stacktrace_unittest.cc src/config_for_unittests.h \ src/base/commandlineflags.h src/stacktrace_config.h \ src/stacktrace_generic-inl.h src/stacktrace_libunwind-inl.h \ - src/stacktrace_powerpc-inl.h src/stacktrace_x86_64-inl.h \ - src/stacktrace_x86-inl.h src/stacktrace_win32-inl.h \ + src/stacktrace_nacl-inl.h src/stacktrace_powerpc-inl.h \ + src/stacktrace_x86_64-inl.h src/stacktrace_x86-inl.h \ + src/stacktrace_win32-inl.h src/base/elf_mem_image.h \ src/base/vdso_support.h src/google/stacktrace.h \ src/base/logging.h src/base/basictypes.h \ src/base/dynamic_annotations.h src/third_party/valgrind.h -@WITH_STACK_TRACE_TRUE@am__objects_39 = $(am__objects_4) \ +@WITH_STACK_TRACE_TRUE@am__objects_40 = $(am__objects_4) \ @WITH_STACK_TRACE_TRUE@ $(am__objects_1) @WITH_STACK_TRACE_TRUE@am_stacktrace_unittest_OBJECTS = \ @WITH_STACK_TRACE_TRUE@ stacktrace_unittest.$(OBJEXT) \ -@WITH_STACK_TRACE_TRUE@ $(am__objects_39) +@WITH_STACK_TRACE_TRUE@ $(am__objects_40) stacktrace_unittest_OBJECTS = $(am_stacktrace_unittest_OBJECTS) @WITH_STACK_TRACE_TRUE@stacktrace_unittest_DEPENDENCIES = \ @WITH_STACK_TRACE_TRUE@ libstacktrace.la liblogging.la @@ -1175,10 +1206,10 @@ am__tcmalloc_and_profiler_unittest_SOURCES_DIST = \ src/tests/tcmalloc_unittest.cc src/tests/testutil.h \ src/tests/testutil.cc src/config_for_unittests.h \ src/google/malloc_extension.h -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_40 = tcmalloc_and_profiler_unittest-tcmalloc_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_41 = tcmalloc_and_profiler_unittest-tcmalloc_unittest.$(OBJEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_and_profiler_unittest-testutil.$(OBJEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_and_profiler_unittest_OBJECTS = $(am__objects_40) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_and_profiler_unittest_OBJECTS = $(am__objects_41) tcmalloc_and_profiler_unittest_OBJECTS = \ $(am_tcmalloc_and_profiler_unittest_OBJECTS) @WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_DEPENDENCIES = libtcmalloc_and_profiler.la @@ -1186,27 +1217,29 @@ am__tcmalloc_both_unittest_SOURCES_DIST = \ src/tests/tcmalloc_unittest.cc src/tests/testutil.h \ src/tests/testutil.cc src/config_for_unittests.h \ src/google/malloc_extension.h -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_both_unittest_OBJECTS = tcmalloc_both_unittest-tcmalloc_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_42 = tcmalloc_both_unittest-tcmalloc_unittest.$(OBJEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_both_unittest-testutil.$(OBJEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_both_unittest_OBJECTS = $(am__objects_42) tcmalloc_both_unittest_OBJECTS = $(am_tcmalloc_both_unittest_OBJECTS) -@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_DEPENDENCIES = $(am__DEPENDENCIES_6) \ +@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__DEPENDENCIES_8 = $(am__DEPENDENCIES_6) \ @WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_5) \ @WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la \ @WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_DEPENDENCIES = $(am__DEPENDENCIES_6) \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__DEPENDENCIES_8 = $(am__DEPENDENCIES_6) \ @WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_5) \ @WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libprofiler.la \ @WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la \ @WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_DEPENDENCIES = $(am__DEPENDENCIES_8) am__tcmalloc_debug_unittest_SOURCES_DIST = \ src/tests/tcmalloc_unittest.cc src/tcmalloc.h \ src/tests/testutil.h src/tests/testutil.cc \ src/config_for_unittests.h src/google/malloc_extension.h -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_41 = tcmalloc_debug_unittest-tcmalloc_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_43 = tcmalloc_debug_unittest-tcmalloc_unittest.$(OBJEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_debug_unittest-testutil.$(OBJEXT) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) -@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_debug_unittest_OBJECTS = $(am__objects_41) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_debug_unittest_OBJECTS = $(am__objects_43) tcmalloc_debug_unittest_OBJECTS = \ $(am_tcmalloc_debug_unittest_OBJECTS) @WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_DEPENDENCIES = libtcmalloc_debug.la \ @@ -1223,12 +1256,12 @@ am__tcmalloc_minimal_debug_unittest_SOURCES_DIST = \ src/tests/tcmalloc_unittest.cc src/tests/testutil.h \ src/tests/testutil.cc src/config_for_unittests.h \ src/google/malloc_extension.h -am__objects_42 = \ +am__objects_44 = \ tcmalloc_minimal_debug_unittest-tcmalloc_unittest.$(OBJEXT) \ tcmalloc_minimal_debug_unittest-testutil.$(OBJEXT) \ $(am__objects_1) @WITH_DEBUGALLOC_TRUE@am_tcmalloc_minimal_debug_unittest_OBJECTS = \ -@WITH_DEBUGALLOC_TRUE@ $(am__objects_42) +@WITH_DEBUGALLOC_TRUE@ $(am__objects_44) tcmalloc_minimal_debug_unittest_OBJECTS = \ $(am_tcmalloc_minimal_debug_unittest_OBJECTS) @WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_DEPENDENCIES = \ @@ -1505,6 +1538,8 @@ GCC_TRUE = @GCC_TRUE@ GREP = @GREP@ HAVE_OBJCOPY_WEAKEN_FALSE = @HAVE_OBJCOPY_WEAKEN_FALSE@ HAVE_OBJCOPY_WEAKEN_TRUE = @HAVE_OBJCOPY_WEAKEN_TRUE@ +HAVE_W_NO_UNUSED_RESULT_FALSE = @HAVE_W_NO_UNUSED_RESULT_FALSE@ +HAVE_W_NO_UNUSED_RESULT_TRUE = @HAVE_W_NO_UNUSED_RESULT_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ @@ -1528,6 +1563,8 @@ NMEDIT = @NMEDIT@ OBJCOPY = @OBJCOPY@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ +OSX_FALSE = @OSX_FALSE@ +OSX_TRUE = @OSX_TRUE@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -1627,7 +1664,8 @@ ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = -I$(top_srcdir)/src $(am__append_1) # This is mostly based on configure options -AM_CXXFLAGS = $(am__append_2) $(am__append_3) $(am__append_4) +AM_CXXFLAGS = $(am__append_2) $(am__append_3) $(am__append_4) \ + $(am__append_5) # The -no-undefined flag allows libtool to generate shared libraries for # Cygwin and MinGW. LIBSTDCXX_LA_LINKER_FLAG is used to fix a Solaris bug. @@ -1646,7 +1684,7 @@ AM_LDFLAGS = -no-undefined $(LIBSTDCXX_LA_LINKER_FLAG) # accomplishes its tasks via patching, leaving no work for the linker # to identify, so the linker will ignore libtcmalloc by default unless # we explicitly create a dependency via -u. -TCMALLOC_FLAGS = $(am__append_5) +TCMALLOC_FLAGS = $(am__append_6) @HAVE_OBJCOPY_WEAKEN_FALSE@WEAKEN = : # If we have objcopy, make malloc/free/etc weak symbols. That way folks @@ -1664,15 +1702,15 @@ TCMALLOC_FLAGS = $(am__append_5) @HAVE_OBJCOPY_WEAKEN_TRUE@ -W __Znwm -W __ZnwmRKSt9nothrow_t -W __Znam -W __ZnamRKSt9nothrow_t \ @HAVE_OBJCOPY_WEAKEN_TRUE@ -W __ZdlPv -W __ZdaPv -LIBS_TO_WEAKEN = libtcmalloc_minimal.la $(am__append_23) \ - $(am__append_34) $(am__append_49) $(am__append_64) +LIBS_TO_WEAKEN = libtcmalloc_minimal.la $(am__append_24) \ + $(am__append_37) $(am__append_54) $(am__append_69) googleincludedir = $(includedir)/google # The .h files you want to install (that is, .h files that people # who install this package can include in their own applications.) # We'll add to this later, on a library-by-library basis -googleinclude_HEADERS = $(am__append_9) \ - $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_28) \ - $(am__append_56) +googleinclude_HEADERS = $(am__append_10) \ + $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_31) \ + $(am__append_61) # tcmalloc.h is a special case, because it's a .h.in file nodist_googleinclude_HEADERS = src/google/tcmalloc.h noinst_HEADERS = src/google/tcmalloc.h.in @@ -1689,7 +1727,7 @@ noinst_HEADERS = src/google/tcmalloc.h.in # end of the world. dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \ README_windows.txt TODO doc/index.html doc/designstyle.css \ - $(am__append_12) doc/tcmalloc.html doc/overview.gif \ + $(am__append_13) doc/tcmalloc.html doc/overview.gif \ doc/pageheap.gif doc/spanmap.gif doc/threadheap.gif \ doc/t-test1.times.txt \ doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png \ @@ -1714,13 +1752,13 @@ dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \ doc/tcmalloc-opspersec.vs.size.5.threads.png \ doc/tcmalloc-opspersec.vs.size.8.threads.png doc/overview.dot \ doc/pageheap.dot doc/spanmap.dot doc/threadheap.dot \ - $(am__append_46) $(am__append_47) $(am__append_61) + $(am__append_51) $(am__append_52) $(am__append_66) # The libraries (.so's) you want to install # We'll add to this later, on a library-by-library basis -lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_22) \ - $(am__append_30) $(am__append_48) $(am__append_57) \ - $(am__append_62) +lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_23) \ + $(am__append_33) $(am__append_53) $(am__append_62) \ + $(am__append_67) # This is for 'convenience libraries' -- basically just a container for sources ### Making the library @@ -1729,12 +1767,12 @@ lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_22) \ # for all files in this library -- except tcmalloc.cc which needs them # to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need # to separate into two libraries. -noinst_LTLIBRARIES = liblogging.la libsysinfo.la $(am__append_6) \ - $(am__append_8) $(am__append_10) \ - libtcmalloc_minimal_internal.la $(am__append_29) +noinst_LTLIBRARIES = liblogging.la libsysinfo.la $(am__append_7) \ + $(am__append_9) $(am__append_11) \ + libtcmalloc_minimal_internal.la $(am__append_32) WINDOWS_PROJECTS = google-perftools.sln \ vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj \ - $(am__append_14) \ + $(am__append_15) \ vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj \ vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj \ vsprojects/tmu-static/tmu-static.vcproj \ @@ -1751,7 +1789,7 @@ WINDOWS_PROJECTS = google-perftools.sln \ vsprojects/realloc_unittest/realloc_unittest.vcproj \ vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj \ vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj \ - $(am__append_37) + $(am__append_42) # unittests you want to run when people type 'make check'. # Note: tests cannot take any arguments! @@ -1770,25 +1808,26 @@ WINDOWS_PROJECTS = google-perftools.sln \ # standard libc! At least, in some situations, some of the time. # These all tests components of tcmalloc_minimal -TESTS = low_level_alloc_unittest atomicops_unittest $(am__append_11) \ +TESTS = low_level_alloc_unittest atomicops_unittest $(am__append_12) \ tcmalloc_minimal_unittest tcmalloc_minimal_large_unittest \ - $(am__append_15) addressmap_unittest $(am__append_18) \ + $(am__append_16) addressmap_unittest $(am__append_19) \ packed_cache_test frag_unittest markidle_unittest \ current_allocated_bytes_test malloc_hook_test \ - malloc_extension_test $(am__append_19) $(am__append_21) \ + malloc_extension_test $(am__append_20) $(am__append_22) \ page_heap_test pagemap_unittest realloc_unittest \ stack_trace_table_test thread_dealloc_unittest \ - $(am__append_24) $(am__append_25) $(am__append_35) \ - $(am__append_40) $(am__append_43) $(am__append_50) \ - $(am__append_52) $(am__append_54) $(am__append_58) \ - $(am__append_63) + $(am__append_25) $(am__append_26) $(am__append_27) \ + $(am__append_28) $(am__append_38) $(am__append_39) \ + $(am__append_40) $(am__append_45) $(am__append_48) \ + $(am__append_55) $(am__append_57) $(am__append_59) \ + $(am__append_63) $(am__append_68) # TESTS_ENVIRONMENT sets environment variables for when you run unittest. # We always get "srcdir" set for free. # We'll add to this later, on a library-by-library basis. -TESTS_ENVIRONMENT = $(am__append_13) $(am__append_36) +TESTS_ENVIRONMENT = $(am__append_14) $(am__append_41) # All script tests should be added here -noinst_SCRIPTS = $(am__append_16) $(am__append_26) $(am__append_38) \ - $(am__append_41) $(am__append_44) $(am__append_59) +noinst_SCRIPTS = $(am__append_17) $(am__append_29) $(am__append_43) \ + $(am__append_46) $(am__append_49) $(am__append_64) # This is my own var, used for extra libraries I make that I need installed EXTRA_INSTALL = @@ -1816,7 +1855,7 @@ SYSINFO_INCLUDES = src/base/sysinfo.h \ libsysinfo_la_SOURCES = src/base/sysinfo.cc \ $(SYSINFO_INCLUDES) -libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_7) +libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_8) # For MinGW, we use also have to use libwindows Luckily, we need the # windows.a library in exactly the same place we need spinlock.a @@ -1891,12 +1930,14 @@ LOW_LEVEL_ALLOC_UNITTEST_INCLUDES = src/base/low_level_alloc.h \ src/google/malloc_hook.h \ src/google/malloc_hook_c.h \ src/malloc_hook-inl.h \ + src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h \ $(SPINLOCK_INCLUDES) \ $(LOGGING_INCLUDES) low_level_alloc_unittest_SOURCES = src/base/low_level_alloc.cc \ src/malloc_hook.cc \ - src/maybe_threads.cc \ + $(MAYBE_THREADS_CC) \ src/tests/low_level_alloc_unittest.cc \ $(LOW_LEVEL_ALLOC_UNITTEST_INCLUDES) @@ -1921,15 +1962,18 @@ atomicops_unittest_LDADD = $(LIBSPINLOCK) @WITH_STACK_TRACE_TRUE@S_STACKTRACE_INCLUDES = src/stacktrace_config.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_generic-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_libunwind-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_nacl-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_powerpc-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_x86_64-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_x86-inl.h \ @WITH_STACK_TRACE_TRUE@ src/stacktrace_win32-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/base/elf_mem_image.h \ @WITH_STACK_TRACE_TRUE@ src/base/vdso_support.h @WITH_STACK_TRACE_TRUE@SG_STACKTRACE_INCLUDES = src/google/stacktrace.h @WITH_STACK_TRACE_TRUE@STACKTRACE_INCLUDES = $(S_STACKTRACE_INCLUDES) $(SG_STACKTRACE_INCLUDES) @WITH_STACK_TRACE_TRUE@libstacktrace_la_SOURCES = src/stacktrace.cc \ +@WITH_STACK_TRACE_TRUE@ src/base/elf_mem_image.cc \ @WITH_STACK_TRACE_TRUE@ src/base/vdso_support.cc \ @WITH_STACK_TRACE_TRUE@ $(STACKTRACE_INCLUDES) @@ -1972,6 +2016,11 @@ S_TCMALLOC_MINIMAL_INCLUDES = src/common.h \ src/sampler.h \ src/central_freelist.h \ src/linked_list.h \ + src/libc_override.h \ + src/libc_override_gcc_and_weak.h \ + src/libc_override_glibc.h \ + src/libc_override_osx.h \ + src/libc_override_redefine.h \ src/page_heap.h \ src/page_heap_allocator.h \ src/span.h \ @@ -1981,6 +2030,8 @@ S_TCMALLOC_MINIMAL_INCLUDES = src/common.h \ src/stack_trace_table.h \ src/base/thread_annotations.h \ src/malloc_hook-inl.h \ + src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h \ src/maybe_threads.h SG_TCMALLOC_MINIMAL_INCLUDES = src/google/malloc_hook.h \ @@ -2055,7 +2106,7 @@ ADDRESSMAP_UNITTEST_INCLUDES = src/addressmap-inl.h \ $(LOGGING_INCLUDES) addressmap_unittest_SOURCES = src/tests/addressmap_unittest.cc \ - $(ADDRESSMAP_UNITTEST_INCLUDES) $(am__append_17) + $(ADDRESSMAP_UNITTEST_INCLUDES) $(am__append_18) addressmap_unittest_CXXFLAGS = -g $(AM_CXXFLAGS) addressmap_unittest_LDADD = liblogging.la @MINGW_FALSE@system_alloc_unittest_SOURCES = src/config_for_unittests.h \ @@ -2110,17 +2161,17 @@ malloc_extension_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_CFLAGS = \ @ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(PTHREAD_CFLAGS) \ @ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(AM_CFLAGS) \ -@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(am__append_20) +@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(am__append_21) @ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) @ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) -@MINGW_FALSE@memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \ -@MINGW_FALSE@ src/tcmalloc.h \ -@MINGW_FALSE@ src/config_for_unittests.h \ -@MINGW_FALSE@ src/tests/testutil.h src/tests/testutil.cc - -@MINGW_FALSE@memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) -@MINGW_FALSE@memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) -@MINGW_FALSE@memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \ +@MINGW_FALSE@@OSX_FALSE@ src/tcmalloc.h \ +@MINGW_FALSE@@OSX_FALSE@ src/config_for_unittests.h \ +@MINGW_FALSE@@OSX_FALSE@ src/tests/testutil.h src/tests/testutil.cc + +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) page_heap_test_SOURCES = src/tests/page_heap_test.cc \ src/config_for_unittests.h \ src/base/logging.h \ @@ -2179,10 +2230,10 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_CXXFLAGS = $(malloc_extension_test_CXXFLAGS) @WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_LDFLAGS = $(malloc_extension_test_LDFLAGS) @WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) -@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_SOURCES = $(memalign_unittest_SOURCES) -@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_CXXFLAGS = $(memalign_unittest_CXXFLAGS) -@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_LDFLAGS = $(memalign_unittest_LDFLAGS) -@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_SOURCES = $(memalign_unittest_SOURCES) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_CXXFLAGS = $(memalign_unittest_CXXFLAGS) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_LDFLAGS = $(memalign_unittest_LDFLAGS) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) @WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_SOURCES = $(realloc_unittest_SOURCES) @WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_CXXFLAGS = $(realloc_unittest_CXXFLAGS) @WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_LDFLAGS = $(realloc_unittest_LDFLAGS) @@ -2226,17 +2277,17 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(NO_EXCEPTIONS) \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_32) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_35) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LDFLAGS = $(PTHREAD_CFLAGS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LIBADD = libstacktrace.la $(PTHREAD_LIBS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_SOURCES = \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_CC) \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_INCLUDES) \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_31) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_34) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_CXXFLAGS = \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_33) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_36) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@ @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LIBADD = libtcmalloc_internal.la $(PTHREAD_LIBS) @WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@HEAP_CHECKER_SOURCES = @@ -2269,14 +2320,22 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) # implementations define their own malloc, and we need to go on the # first linkline to make sure our malloc 'wins'. @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_LDADD = $(LIBTCMALLOC) liblogging.la $(PTHREAD_LIBS) -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/testutil.h src/tests/testutil.cc \ -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_UNITTEST_INCLUDES) -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) -@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) -@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ -@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la $(PTHREAD_LIBS) +# This makes sure it's safe to link in both tcmalloc and +# tcmalloc_minimal. (One would never do this on purpose, but perhaps +# by accident...) When we can compile libprofiler, we also link it in +# to make sure that works too. NOTE: On OS X, it's *not* safe to +# link both in (we end up with two copies of every global var, and +# the code tends to pick one arbitrarily), so don't run the test there. +# (We define these outside the 'if' because they're reused below.) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_srcs = src/tests/tcmalloc_unittest.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/testutil.h src/tests/testutil.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_UNITTEST_INCLUDES) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_cflags = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_lflags = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_ladd = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ +@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la $(PTHREAD_LIBS) # We want libtcmalloc last on the link line, but due to a bug in # libtool involving convenience libs, they need to come last on the @@ -2285,9 +2344,13 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) # We also put pthreads after tcmalloc, because some pthread # implementations define their own malloc, and we need to go on the # first linkline to make sure our malloc 'wins'. -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libprofiler.la liblogging.la $(PTHREAD_LIBS) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_ladd = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libprofiler.la liblogging.la $(PTHREAD_LIBS) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_SOURCES = $(tcmalloc_both_unittest_srcs) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_CXXFLAGS = $(tcmalloc_both_unittest_cflags) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_LDFLAGS = $(tcmalloc_both_unittest_lflags) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_LDADD = $(tcmalloc_both_unittest_ladd) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) @WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) @@ -2475,9 +2538,9 @@ thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) # libstacktrace.la, which we already get via libtcmalloc. Trying to # specify it twice causes link-time duplicate-definition errors. :-( @WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_LIBADD = $(libtcmalloc_la_LIBADD) -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_SOURCES = $(tcmalloc_both_unittest_SOURCES) -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_CXXFLAGS = $(tcmalloc_both_unittest_CXXFLAGS) -@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_LDFLAGS = $(tcmalloc_both_unittest_LDFLAGS) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_SOURCES = $(tcmalloc_both_unittest_srcs) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_CXXFLAGS = $(tcmalloc_both_unittest_cflags) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_LDFLAGS = $(tcmalloc_both_unittest_lflags) @WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_LDADD = libtcmalloc_and_profiler.la # http://linux.die.net/man/1/pkg-config, http://pkg-config.freedesktop.org/wiki @@ -2865,6 +2928,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debugallocation_test-debugallocation_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynamic_annotations.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf_mem_image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frag_unittest-frag_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getpc_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po@am__quote@ @@ -3121,6 +3185,13 @@ stacktrace.lo: src/stacktrace.cc @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o stacktrace.lo `test -f 'src/stacktrace.cc' || echo '$(srcdir)/'`src/stacktrace.cc +elf_mem_image.lo: src/base/elf_mem_image.cc +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT elf_mem_image.lo -MD -MP -MF "$(DEPDIR)/elf_mem_image.Tpo" -c -o elf_mem_image.lo `test -f 'src/base/elf_mem_image.cc' || echo '$(srcdir)/'`src/base/elf_mem_image.cc; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/elf_mem_image.Tpo" "$(DEPDIR)/elf_mem_image.Plo"; else rm -f "$(DEPDIR)/elf_mem_image.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/elf_mem_image.cc' object='elf_mem_image.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o elf_mem_image.lo `test -f 'src/base/elf_mem_image.cc' || echo '$(srcdir)/'`src/base/elf_mem_image.cc + vdso_support.lo: src/base/vdso_support.cc @am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT vdso_support.lo -MD -MP -MF "$(DEPDIR)/vdso_support.Tpo" -c -o vdso_support.lo `test -f 'src/base/vdso_support.cc' || echo '$(srcdir)/'`src/base/vdso_support.cc; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/vdso_support.Tpo" "$(DEPDIR)/vdso_support.Plo"; else rm -f "$(DEPDIR)/vdso_support.Tpo"; exit 1; fi @@ -5014,8 +5085,8 @@ libtcmalloc.pc: Makefile packages/rpm/rpm.spec echo '' >> "$@".tmp echo 'Name: $(PACKAGE)' >> "$@".tmp echo 'Version: $(VERSION)' >> "$@".tmp - -grep '^Summary:' packages/rpm/rpm.spec | sed s/^Summary:/Description:/ | head -n1 >> "$@".tmp - -grep '^URL: ' packages/rpm/rpm.spec >> "$@".tmp + -grep '^Summary:' $(top_srcdir)/packages/rpm/rpm.spec | sed s/^Summary:/Description:/ | head -n1 >> "$@".tmp + -grep '^URL: ' $(top_srcdir)/packages/rpm/rpm.spec >> "$@".tmp echo 'Requires:' >> "$@".tmp echo 'Libs: -L$${libdir} -ltcmalloc' >> "$@".tmp echo 'Libs.private: $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)' >> "$@".tmp diff --git a/third_party/tcmalloc/vendor/NEWS b/third_party/tcmalloc/vendor/NEWS index 62a2f62..52bb1fb 100644 --- a/third_party/tcmalloc/vendor/NEWS +++ b/third_party/tcmalloc/vendor/NEWS @@ -1,4 +1,35 @@ -== 7 February 2011 == +== 15 July 2011 == + +I've just released perftools 1.8 + +Of the many changes in this release, a good number pertain to porting. +I've revamped OS X support to use the malloc-zone framework; it should +now Just Work to link in tcmalloc, without needing +`DYLD_FORCE_FLAT_NAMESPACE` or the like. (This is a pretty major +change, so please feel free to report feedback at +google-perftools@googlegroups.com.) 64-bit Windows support is also +improved, as is ARM support, and the hooks are in place to improve +FreeBSD support as well. + +On the other hand, I'm seeing hanging tests on Cygwin. I see the same +hanging even with (the old) perftools 1.7, so I'm guessing this is +either a problem specific to my Cygwin installation, or nobody is +trying to use perftools under Cygwin. If you can reproduce the +problem, and even better have a solution, you can report it at +google-perftools@googlegroups.com. + +Internal changes include several performance and space-saving tweaks. +One is user-visible (but in "stealth mode", and otherwise +undocumented): you can compile with `-DTCMALLOC_SMALL_BUT_SLOW`. In +this mode, tcmalloc will use less memory overhead, at the cost of +running (likely not noticeably) slower. + +There are many other changes as well, too numerous to recount here, +but present in the +[http://google-perftools.googlecode.com/svn/tags/perftools-1.8/ChangeLog ChangeLog]. + + +=== 7 February 2011 === Thanks to endlessr..., who [http://code.google.com/p/google-perftools/issues/detail?id=307 identified] @@ -9,7 +40,7 @@ some aggressive optimizations used in MSVC 10. I'll fix the test, but in the meantime, feel free to use perftools even when compiled under MSVC 10. -== 4 February 2011 == +=== 4 February 2011 === I've just released perftools 1.7 diff --git a/third_party/tcmalloc/vendor/README b/third_party/tcmalloc/vendor/README index 21b18d5..204562a 100644 --- a/third_party/tcmalloc/vendor/README +++ b/third_party/tcmalloc/vendor/README @@ -204,28 +204,6 @@ that error. To fix it, just comment out (or delete) the line in your config.h file before building. -OS X ISSUES ------------ - -You may need to set the environment variable DYLD_FORCE_FLAT_NAMESPACE -to use perftools with OS X. Because of how OS X does symbol binding, -libc routines will use libc malloc even when the binary is linked with --ltcmalloc. This is not usually a problem, but becomes one if the -application is responsible for freeing that memory: the application -will use tcmalloc's free() to try to free memory allocated with libc's -malloc(), which will cause no end of confusion. - -One (or both) of these workaround may fix the problem: - DYLD_FORCE_FLAT_NAMESPACE=1 myapp - DYLD_INSERT_LIBRARIES=path/to/libtcmalloc.dylib myapp - -The best solution may depend on the version of OS X being used. -Neither solution is likely to work if you dlopen() libraries from -within your application. If you have any experience with this, we'd -appreciate you sharing it at - http://groups.google.com/group/google-perftools - - 64-BIT ISSUES ------------- diff --git a/third_party/tcmalloc/vendor/configure b/third_party/tcmalloc/vendor/configure index 6e8fb4d..9f19ef0 100644 --- a/third_party/tcmalloc/vendor/configure +++ b/third_party/tcmalloc/vendor/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for google-perftools 1.7. +# Generated by GNU Autoconf 2.65 for google-perftools 1.8. # # Report bugs to <opensource@google.com>. # @@ -701,8 +701,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='google-perftools' PACKAGE_TARNAME='google-perftools' -PACKAGE_VERSION='1.7' -PACKAGE_STRING='google-perftools 1.7' +PACKAGE_VERSION='1.8' +PACKAGE_STRING='google-perftools 1.8' PACKAGE_BUGREPORT='opensource@google.com' PACKAGE_URL='' @@ -758,6 +758,8 @@ WITH_HEAP_PROFILER_FALSE WITH_HEAP_PROFILER_TRUE WITH_CPU_PROFILER_FALSE WITH_CPU_PROFILER_TRUE +OSX_FALSE +OSX_TRUE MINGW_FALSE MINGW_TRUE PTHREAD_CFLAGS @@ -766,6 +768,8 @@ PTHREAD_CC acx_pthread_config LIBSTDCXX_LA_LINKER_FLAG NANOSLEEP_LIBS +HAVE_W_NO_UNUSED_RESULT_FALSE +HAVE_W_NO_UNUSED_RESULT_TRUE X86_64_AND_NO_FP_BY_DEFAULT_FALSE X86_64_AND_NO_FP_BY_DEFAULT_TRUE ENABLE_FRAME_POINTERS_FALSE @@ -1468,7 +1472,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures google-perftools 1.7 to adapt to many kinds of systems. +\`configure' configures google-perftools 1.8 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1539,7 +1543,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of google-perftools 1.7:";; + short | recursive ) echo "Configuration of google-perftools 1.8:";; esac cat <<\_ACEOF @@ -1649,7 +1653,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -google-perftools configure 1.7 +google-perftools configure 1.8 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. @@ -2234,7 +2238,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by google-perftools $as_me 1.7, which was +It was created by google-perftools $as_me 1.8, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -2586,8 +2590,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu # Update this value for every release! (A:B:C will map to foo.so.(A-C).C.B) # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -TCMALLOC_SO_VERSION=1:0:1 -PROFILER_SO_VERSION=1:0:1 +TCMALLOC_SO_VERSION=2:0:2 +PROFILER_SO_VERSION=1:1:1 @@ -2979,7 +2983,7 @@ fi # Define the identity of the package. PACKAGE='google-perftools' - VERSION='1.7' + VERSION='1.8' cat >>confdefs.h <<_ACEOF @@ -5609,13 +5613,13 @@ if test "${lt_cv_nm_interface+set}" = set; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:5612: $ac_compile\"" >&5) + (eval echo "\"\$as_me:5616: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:5615: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:5619: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:5618: output\"" >&5) + (eval echo "\"\$as_me:5622: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -6820,7 +6824,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6823 "configure"' > conftest.$ac_ext + echo '#line 6827 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -8693,11 +8697,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8696: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8700: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8700: \$? = $ac_status" >&5 + echo "$as_me:8704: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -9032,11 +9036,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9035: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9039: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:9039: \$? = $ac_status" >&5 + echo "$as_me:9043: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -9137,11 +9141,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9140: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9144: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9144: \$? = $ac_status" >&5 + echo "$as_me:9148: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -9192,11 +9196,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9195: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9199: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9199: \$? = $ac_status" >&5 + echo "$as_me:9203: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -11576,7 +11580,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11579 "configure" +#line 11583 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11672,7 +11676,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11675 "configure" +#line 11679 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13628,11 +13632,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13631: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13635: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:13635: \$? = $ac_status" >&5 + echo "$as_me:13639: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -13727,11 +13731,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13730: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13734: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:13734: \$? = $ac_status" >&5 + echo "$as_me:13738: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -13779,11 +13783,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13782: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13786: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:13786: \$? = $ac_status" >&5 + echo "$as_me:13790: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -15949,6 +15953,52 @@ fi rm fp.s CFLAGS="$OLD_CFLAGS" +# See if the compiler supports -Wno-unused-result. +# Newer ubuntu's turn on -D_FORTIFY_SOURCE=2, enabling +# __attribute__((warn_unused_result)) for things like write(), +# which we don't care about. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler supports -Wno-unused-result" >&5 +$as_echo_n "checking if the compiler supports -Wno-unused-result... " >&6; } +if test "${perftools_cv_w_no_unused_result+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + OLD_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wno-error -Wno-unused-result" + # gcc doesn't warn about unknown flags unless it's + # also warning for some other purpose, hence the + # divide-by-0. (We use -Wno-error to make sure the + # divide-by-0 doesn't cause this test to fail!) + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +return 1/0 + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + perftools_cv_w_no_unused_result=yes +else + perftools_cv_w_no_unused_result=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$OLD_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $perftools_cv_w_no_unused_result" >&5 +$as_echo "$perftools_cv_w_no_unused_result" >&6; } + + +if test "$perftools_cv_w_no_unused_result" = yes; then + HAVE_W_NO_UNUSED_RESULT_TRUE= + HAVE_W_NO_UNUSED_RESULT_FALSE='#' +else + HAVE_W_NO_UNUSED_RESULT_TRUE='#' + HAVE_W_NO_UNUSED_RESULT_FALSE= +fi + # Defines PRIuS { $as_echo "$as_me:${as_lineno-$LINENO}: checking printf format code for printing a size_t and ssize_t" >&5 @@ -16115,6 +16165,35 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext +# glibc's __malloc_hook/etc were declared volatile starting in glibc 2.14 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if __malloc_hook is declared volatile" >&5 +$as_echo_n "checking if __malloc_hook is declared volatile... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <malloc.h> +void* (* volatile __malloc_hook)(size_t, const void*) = 0; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define MALLOC_HOOK_MAYBE_VOLATILE volatile" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + $as_echo "#define MALLOC_HOOK_MAYBE_VOLATILE /**/" >>confdefs.h +, + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + # Nanosleep requires extra libraries on some architectures (solaris). # This sets NANOSLEEP_LIBS. nanosleep doesn't exist on mingw, which # is fine for us because we don't compile libspinlock, which uses it. @@ -16977,10 +17056,15 @@ $as_echo "#define PERFTOOLS_DLL_DECL /**/" >>confdefs.h # http://code.google.com/p/google-perftools/issues/detail?id=246 + + # MinGW uses autoconf, but also needs the windows shim routines # (since it doesn't have its own support for, say, pthreads). # This requires us to #include a special header file, and also to # link in some windows versions of .o's instead of the unix versions. +# +# Also, manually mark systems where we have to be careful how early +# we run pthreads. TODO(csilvers): turn this into an autoconf check. @@ -16993,6 +17077,16 @@ else fi + +if expr $host : '.*-apple-darwin.*' >/dev/null 2>&1; then + OSX_TRUE= + OSX_FALSE='#' +else + OSX_TRUE='#' + OSX_FALSE= +fi + + # Redhat 7 (and below?) has sys/ucontext.h, but if you try to #include # it directly, the compiler gets upset. So we pretend we don't have # it. @@ -17211,10 +17305,18 @@ if test -z "${X86_64_AND_NO_FP_BY_DEFAULT_TRUE}" && test -z "${X86_64_AND_NO_FP_ as_fn_error "conditional \"X86_64_AND_NO_FP_BY_DEFAULT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${HAVE_W_NO_UNUSED_RESULT_TRUE}" && test -z "${HAVE_W_NO_UNUSED_RESULT_FALSE}"; then + as_fn_error "conditional \"HAVE_W_NO_UNUSED_RESULT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MINGW_TRUE}" && test -z "${MINGW_FALSE}"; then as_fn_error "conditional \"MINGW\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${OSX_TRUE}" && test -z "${OSX_FALSE}"; then + as_fn_error "conditional \"OSX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${WITH_CPU_PROFILER_TRUE}" && test -z "${WITH_CPU_PROFILER_FALSE}"; then as_fn_error "conditional \"WITH_CPU_PROFILER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -17647,7 +17749,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by google-perftools $as_me 1.7, which was +This file was extended by google-perftools $as_me 1.8, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17713,7 +17815,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -google-perftools config.status 1.7 +google-perftools config.status 1.8 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" diff --git a/third_party/tcmalloc/vendor/configure.ac b/third_party/tcmalloc/vendor/configure.ac index 87507ce..4eb8bf5 100644 --- a/third_party/tcmalloc/vendor/configure.ac +++ b/third_party/tcmalloc/vendor/configure.ac @@ -4,11 +4,11 @@ # make sure we're interpreted by some minimal autoconf AC_PREREQ(2.57) -AC_INIT(google-perftools, 1.7, opensource@google.com) +AC_INIT(google-perftools, 1.8, opensource@google.com) # Update this value for every release! (A:B:C will map to foo.so.(A-C).C.B) # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -TCMALLOC_SO_VERSION=1:0:1 -PROFILER_SO_VERSION=1:0:1 +TCMALLOC_SO_VERSION=2:0:2 +PROFILER_SO_VERSION=1:1:1 AC_SUBST(TCMALLOC_SO_VERSION) AC_SUBST(PROFILER_SO_VERSION) @@ -238,6 +238,24 @@ AM_CONDITIONAL(X86_64_AND_NO_FP_BY_DEFAULT, rm fp.s CFLAGS="$OLD_CFLAGS" +# See if the compiler supports -Wno-unused-result. +# Newer ubuntu's turn on -D_FORTIFY_SOURCE=2, enabling +# __attribute__((warn_unused_result)) for things like write(), +# which we don't care about. +AC_CACHE_CHECK([if the compiler supports -Wno-unused-result], + perftools_cv_w_no_unused_result, + [OLD_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wno-error -Wno-unused-result" + # gcc doesn't warn about unknown flags unless it's + # also warning for some other purpose, hence the + # divide-by-0. (We use -Wno-error to make sure the + # divide-by-0 doesn't cause this test to fail!) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, return 1/0)], + perftools_cv_w_no_unused_result=yes, + perftools_cv_w_no_unused_result=no) + CFLAGS="$OLD_CFLAGS"]) +AM_CONDITIONAL(HAVE_W_NO_UNUSED_RESULT, + test "$perftools_cv_w_no_unused_result" = yes) # Defines PRIuS AC_COMPILER_CHARACTERISTICS @@ -276,10 +294,20 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([#if defined(__GNUC__) && (defined(__i386__) || #error gcc has this bug: http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html #endif], [static __thread int p = 0])], [AC_DEFINE(HAVE_TLS, 1, - Define to 1 if compiler supports __thread) + Define to 1 if compiler supports __thread) AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) +# glibc's __malloc_hook/etc were declared volatile starting in glibc 2.14 +AC_MSG_CHECKING([if __malloc_hook is declared volatile]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <malloc.h> +void* (* volatile __malloc_hook)(size_t, const void*) = 0;],)], + [AC_DEFINE(MALLOC_HOOK_MAYBE_VOLATILE, volatile, + Define to 'volatile' if __malloc_hook is declared volatile) + AC_MSG_RESULT([yes])], + [AC_DEFINE(MALLOC_HOOK_MAYBE_VOLATILE, ), + AC_MSG_RESULT([no])]) + # Nanosleep requires extra libraries on some architectures (solaris). # This sets NANOSLEEP_LIBS. nanosleep doesn't exist on mingw, which # is fine for us because we don't compile libspinlock, which uses it. @@ -334,10 +362,20 @@ AH_TOP([ #define GOOGLE_PERFTOOLS_CONFIG_H_ ]) +AH_VERBATIM([PTHREADS_CRASHES_IF_RUN_TOO_EARLY], + [/* Mark the systems where we know it's bad if pthreads runs too + early before main (before threads are initialized, presumably). */ +#ifdef __FreeBSD__ +#define PTHREADS_CRASHES_IF_RUN_TOO_EARLY 1 +#endif]) + # MinGW uses autoconf, but also needs the windows shim routines # (since it doesn't have its own support for, say, pthreads). # This requires us to #include a special header file, and also to # link in some windows versions of .o's instead of the unix versions. +# +# Also, manually mark systems where we have to be careful how early +# we run pthreads. TODO(csilvers): turn this into an autoconf check. AH_BOTTOM([ #ifdef __MINGW32__ #include "windows/mingw.h" @@ -346,6 +384,7 @@ AH_BOTTOM([ #endif /* #ifndef GOOGLE_PERFTOOLS_CONFIG_H_ */ ]) AM_CONDITIONAL(MINGW, expr $host : '.*-mingw' >/dev/null 2>&1) +AM_CONDITIONAL(OSX, expr $host : '.*-apple-darwin.*' >/dev/null 2>&1) # Redhat 7 (and below?) has sys/ucontext.h, but if you try to #include # it directly, the compiler gets upset. So we pretend we don't have diff --git a/third_party/tcmalloc/vendor/doc/heapprofile.html b/third_party/tcmalloc/vendor/doc/heapprofile.html index 709559d..22bfbec 100644 --- a/third_party/tcmalloc/vendor/doc/heapprofile.html +++ b/third_party/tcmalloc/vendor/doc/heapprofile.html @@ -366,11 +366,8 @@ interactive mode.</p> </ul> <hr> -<address>Sanjay Ghemawat<br> +<address>Sanjay Ghemawat <!-- Created: Tue Dec 19 10:43:14 PST 2000 --> -<!-- hhmts start --> -Last modified: Sat Feb 24 14:33:15 PST 2007 (csilvers) -<!-- hhmts end --> </address> </body> </html> diff --git a/third_party/tcmalloc/vendor/doc/tcmalloc.html b/third_party/tcmalloc/vendor/doc/tcmalloc.html index 4578984..8d72c0c 100644 --- a/third_party/tcmalloc/vendor/doc/tcmalloc.html +++ b/third_party/tcmalloc/vendor/doc/tcmalloc.html @@ -503,7 +503,7 @@ environment variables.</p> </tr> <tr valign=top> - <td><code>TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES=<i>x</i></code></td> + <td><code>TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES</code></td> <td>default: 16777216</td> <td> Bound on the total amount of bytes allocated to thread caches. This diff --git a/third_party/tcmalloc/vendor/google-perftools.sln b/third_party/tcmalloc/vendor/google-perftools.sln index 8d7f528..b2fb893 100644 --- a/third_party/tcmalloc/vendor/google-perftools.sln +++ b/third_party/tcmalloc/vendor/google-perftools.sln @@ -131,10 +131,18 @@ Global {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug.Build.0 = Debug|Win32 {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release.ActiveCfg = Release|Win32 {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release.Build.0 = Release|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Debug.ActiveCfg = Debug|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Debug.Build.0 = Debug|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release.ActiveCfg = Release|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release.Build.0 = Release|Win32 {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug.ActiveCfg = Debug|Win32 {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug.Build.0 = Debug|Win32 {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release.ActiveCfg = Release|Win32 {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release.Build.0 = Release|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug.ActiveCfg = Debug|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug.Build.0 = Debug|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release.ActiveCfg = Release|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release.Build.0 = Release|Win32 {605D3CED-B530-424E-B7D2-2A31F14FD570}.Debug.ActiveCfg = Debug|Win32 {605D3CED-B530-424E-B7D2-2A31F14FD570}.Debug.Build.0 = Debug|Win32 {605D3CED-B530-424E-B7D2-2A31F14FD570}.Release.ActiveCfg = Release|Win32 diff --git a/third_party/tcmalloc/vendor/packages/deb/changelog b/third_party/tcmalloc/vendor/packages/deb/changelog index e9fd548..703500b 100644 --- a/third_party/tcmalloc/vendor/packages/deb/changelog +++ b/third_party/tcmalloc/vendor/packages/deb/changelog @@ -1,3 +1,9 @@ +google-perftools (1.8-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. <opensource@google.com> Fri, 15 Jul 2011 16:10:51 -0700 + google-perftools (1.7-1) unstable; urgency=low * New upstream release. @@ -140,7 +146,7 @@ google-perftools (0.5-1) unstable; urgency=low * New upstream release. - -- Google Inc. <opensource@google.com> Mon Nov 14 17:28:59 2005 + -- Google Inc. <opensource@google.com> Mon Nov 14 17:28:59 2005 -0800 google-perftools (0.4-1) unstable; urgency=low diff --git a/third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h b/third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h index 58782a17..bd42c82 100644 --- a/third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h +++ b/third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h @@ -55,28 +55,74 @@ typedef int64 Atomic64; // 32-bit low-level operations on any platform +extern "C" { +// We use windows intrinsics when we can (they seem to be supported +// well on MSVC 8.0 and above). Unfortunately, in some +// environments, <windows.h> and <intrin.h> have conflicting +// declarations of some other intrinsics, breaking compilation: +// http://connect.microsoft.com/VisualStudio/feedback/details/262047 +// Therefore, we simply declare the relevant intrinsics ourself. + // MinGW has a bug in the header files where it doesn't indicate the // first argument is volatile -- they're not up to date. See // http://readlist.com/lists/lists.sourceforge.net/mingw-users/0/3861.html // We have to const_cast away the volatile to avoid compiler warnings. // TODO(csilvers): remove this once MinGW has updated MinGW/include/winbase.h -#ifdef __MINGW32__ -inline LONG InterlockedCompareExchange(volatile LONG* ptr, - LONG newval, LONG oldval) { +#if defined(__MINGW32__) +inline LONG FastInterlockedCompareExchange(volatile LONG* ptr, + LONG newval, LONG oldval) { return ::InterlockedCompareExchange(const_cast<LONG*>(ptr), newval, oldval); } -inline LONG InterlockedExchange(volatile LONG* ptr, LONG newval) { +inline LONG FastInterlockedExchange(volatile LONG* ptr, LONG newval) { return ::InterlockedExchange(const_cast<LONG*>(ptr), newval); } -inline LONG InterlockedExchangeAdd(volatile LONG* ptr, LONG increment) { +inline LONG FastInterlockedExchangeAdd(volatile LONG* ptr, LONG increment) { return ::InterlockedExchangeAdd(const_cast<LONG*>(ptr), increment); } + +#elif _MSC_VER >= 1400 // intrinsics didn't work so well before MSVC 8.0 +// Unfortunately, in some environments, <windows.h> and <intrin.h> +// have conflicting declarations of some intrinsics, breaking +// compilation. So we declare the intrinsics we need ourselves. See +// http://connect.microsoft.com/VisualStudio/feedback/details/262047 +LONG _InterlockedCompareExchange(volatile LONG* ptr, LONG newval, LONG oldval); +#pragma intrinsic(_InterlockedCompareExchange) +inline LONG FastInterlockedCompareExchange(volatile LONG* ptr, + LONG newval, LONG oldval) { + return _InterlockedCompareExchange(ptr, newval, oldval); +} + +LONG _InterlockedExchange(volatile LONG* ptr, LONG newval); +#pragma intrinsic(_InterlockedExchange) +inline LONG FastInterlockedExchange(volatile LONG* ptr, LONG newval) { + return _InterlockedExchange(ptr, newval); +} + +LONG _InterlockedExchangeAdd(volatile LONG* ptr, LONG increment); +#pragma intrinsic(_InterlockedExchangeAdd) +inline LONG FastInterlockedExchangeAdd(volatile LONG* ptr, LONG increment) { + return _InterlockedExchangeAdd(ptr, increment); +} + +#else +inline LONG FastInterlockedCompareExchange(volatile LONG* ptr, + LONG newval, LONG oldval) { + return ::InterlockedCompareExchange(ptr, newval, oldval); +} +inline LONG FastInterlockedExchange(volatile LONG* ptr, LONG newval) { + return ::InterlockedExchange(ptr, newval); +} +inline LONG FastInterlockedExchangeAdd(volatile LONG* ptr, LONG increment) { + return ::InterlockedExchangeAdd(ptr, increment); +} + #endif // ifdef __MINGW32__ +} // extern "C" inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { - LONG result = InterlockedCompareExchange( + LONG result = FastInterlockedCompareExchange( reinterpret_cast<volatile LONG*>(ptr), static_cast<LONG>(new_value), static_cast<LONG>(old_value)); @@ -85,7 +131,7 @@ inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value) { - LONG result = InterlockedExchange( + LONG result = FastInterlockedExchange( reinterpret_cast<volatile LONG*>(ptr), static_cast<LONG>(new_value)); return static_cast<Atomic32>(result); @@ -93,7 +139,7 @@ inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment) { - return InterlockedExchangeAdd( + return FastInterlockedExchangeAdd( reinterpret_cast<volatile LONG*>(ptr), static_cast<LONG>(increment)) + increment; } @@ -173,27 +219,68 @@ inline Atomic32 Release_Load(volatile const Atomic32* ptr) { COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic); -// Like for the __MINGW32__ case above, this works around a header -// error in mingw, where it's missing 'volatile'. -#ifdef __MINGW64__ -inline PVOID InterlockedCompareExchangePointer(volatile PVOID* ptr, - PVOID newval, PVOID oldval) { +// These are the intrinsics needed for 64-bit operations. Similar to the +// 32-bit case above. + +extern "C" { +#if defined(__MINGW64__) +inline PVOID FastInterlockedCompareExchangePointer(volatile PVOID* ptr, + PVOID newval, PVOID oldval) { return ::InterlockedCompareExchangePointer(const_cast<PVOID*>(ptr), newval, oldval); } -inline PVOID InterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) { +inline PVOID FastInterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) { return ::InterlockedExchangePointer(const_cast<PVOID*>(ptr), newval); } -inline LONGLONG InterlockedExchangeAdd64(volatile LONGLONG* ptr, - LONGLONG increment) { +inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr, + LONGLONG increment) { return ::InterlockedExchangeAdd64(const_cast<LONGLONG*>(ptr), increment); } + +#elif _MSC_VER >= 1400 // intrinsics didn't work so well before MSVC 8.0 +// Like above, we need to declare the intrinsics ourselves. +PVOID _InterlockedCompareExchangePointer(volatile PVOID* ptr, + PVOID newval, PVOID oldval); +#pragma intrinsic(_InterlockedCompareExchangePointer) +inline PVOID FastInterlockedCompareExchangePointer(volatile PVOID* ptr, + PVOID newval, PVOID oldval) { + return _InterlockedCompareExchangePointer(const_cast<PVOID*>(ptr), + newval, oldval); +} + +PVOID _InterlockedExchangePointer(volatile PVOID* ptr, PVOID newval); +#pragma intrinsic(_InterlockedExchangePointer) +inline PVOID FastInterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) { + return _InterlockedExchangePointer(const_cast<PVOID*>(ptr), newval); +} + +LONGLONG _InterlockedExchangeAdd64(volatile LONGLONG* ptr, LONGLONG increment); +#pragma intrinsic(_InterlockedExchangeAdd64) +inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr, + LONGLONG increment) { + return _InterlockedExchangeAdd64(const_cast<LONGLONG*>(ptr), increment); +} + +#else +inline PVOID FastInterlockedCompareExchangePointer(volatile PVOID* ptr, + PVOID newval, PVOID oldval) { + return ::InterlockedCompareExchangePointer(ptr, newval, oldval); +} +inline PVOID FastInterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) { + return ::InterlockedExchangePointer(ptr, newval); +} +inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr, + LONGLONG increment) { + return ::InterlockedExchangeAdd64(ptr, increment); +} + #endif // ifdef __MINGW64__ +} // extern "C" inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, Atomic64 old_value, Atomic64 new_value) { - PVOID result = InterlockedCompareExchangePointer( + PVOID result = FastInterlockedCompareExchangePointer( reinterpret_cast<volatile PVOID*>(ptr), reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value)); return reinterpret_cast<Atomic64>(result); @@ -201,7 +288,7 @@ inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value) { - PVOID result = InterlockedExchangePointer( + PVOID result = FastInterlockedExchangePointer( reinterpret_cast<volatile PVOID*>(ptr), reinterpret_cast<PVOID>(new_value)); return reinterpret_cast<Atomic64>(result); @@ -209,7 +296,7 @@ inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment) { - return InterlockedExchangeAdd64( + return FastInterlockedExchangeAdd64( reinterpret_cast<volatile LONGLONG*>(ptr), static_cast<LONGLONG>(increment)) + increment; } @@ -258,7 +345,7 @@ inline Atomic64 Release_Load(volatile const Atomic64* ptr) { // 64-bit low-level operations on 32-bit platform // TODO(vchen): The GNU assembly below must be converted to MSVC inline -// assembly. Then the file should be renamed to ...-x86-mscv.h, probably. +// assembly. Then the file should be renamed to ...-x86-msvc.h, probably. inline void NotImplementedFatalError(const char *function_name) { fprintf(stderr, "64-bit %s() not implemented on this platform\n", diff --git a/third_party/tcmalloc/vendor/src/base/atomicops.h b/third_party/tcmalloc/vendor/src/base/atomicops.h index f36df5f..17e8a27 100644 --- a/third_party/tcmalloc/vendor/src/base/atomicops.h +++ b/third_party/tcmalloc/vendor/src/base/atomicops.h @@ -96,7 +96,7 @@ #elif defined(ARMV3) #include "base/atomicops-internals-arm-generic.h" #elif defined(_WIN32) -#include "base/atomicops-internals-x86-windows.h" +#include "base/atomicops-internals-windows.h" #elif defined(__GNUC__) && (defined(__i386) || defined(__x86_64__)) #include "base/atomicops-internals-x86.h" #elif defined(__linux__) && defined(__PPC__) diff --git a/third_party/tcmalloc/vendor/src/base/cycleclock.h b/third_party/tcmalloc/vendor/src/base/cycleclock.h index 11f9c9b..db5f49a 100644 --- a/third_party/tcmalloc/vendor/src/base/cycleclock.h +++ b/third_party/tcmalloc/vendor/src/base/cycleclock.h @@ -50,16 +50,20 @@ #if defined(__MACH__) && defined(__APPLE__) # include <mach/mach_time.h> #endif -// For MSVC, we want the __rdtsc intrinsic, declared in <intrin.h>. -// Unfortunately, in some environments, <windows.h> and <intrin.h> have -// conflicting declarations of some other intrinsics, breaking compilation. +// For MSVC, we want to use '_asm rdtsc' when possible (since it works +// with even ancient MSVC compilers), and when not possible the +// __rdtsc intrinsic, declared in <intrin.h>. Unfortunately, in some +// environments, <windows.h> and <intrin.h> have conflicting +// declarations of some other intrinsics, breaking compilation. // Therefore, we simply declare __rdtsc ourselves. See also // http://connect.microsoft.com/VisualStudio/feedback/details/262047 -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(_M_IX86) extern "C" uint64 __rdtsc(); #pragma intrinsic(__rdtsc) #endif +#ifdef ARMV3 #include <sys/time.h> +#endif // NOTE: only i386 and x86_64 have been well tested. // PPC, sparc, alpha, and ia64 are based on @@ -106,6 +110,12 @@ struct CycleClock { int64 itc; asm("mov %0 = ar.itc" : "=r" (itc)); return itc; +#elif defined(_MSC_VER) && defined(_M_IX86) + // Older MSVC compilers (like 7.x) don't seem to support the + // __rdtsc intrinsic properly, so I prefer to use _asm instead + // when I know it will work. Otherwise, I'll use __rdtsc and hope + // the code is being compiled with a non-ancient compiler. + _asm rdtsc #elif defined(_MSC_VER) return __rdtsc(); #elif defined(ARMV3) diff --git a/third_party/tcmalloc/vendor/src/base/elf_mem_image.cc b/third_party/tcmalloc/vendor/src/base/elf_mem_image.cc new file mode 100644 index 0000000..d8b8090 --- /dev/null +++ b/third_party/tcmalloc/vendor/src/base/elf_mem_image.cc @@ -0,0 +1,432 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Paul Pluzhnikov +// +// Allow dynamic symbol lookup in an in-memory Elf image. +// + +#include "base/elf_mem_image.h" + +#ifdef HAVE_ELF_MEM_IMAGE // defined in elf_mem_image.h + +#include "base/logging.h" + +// From binutils/include/elf/common.h (this doesn't appear to be documented +// anywhere else). +// +// /* This flag appears in a Versym structure. It means that the symbol +// is hidden, and is only visible with an explicit version number. +// This is a GNU extension. */ +// #define VERSYM_HIDDEN 0x8000 +// +// /* This is the mask for the rest of the Versym information. */ +// #define VERSYM_VERSION 0x7fff + +#define VERSYM_VERSION 0x7fff + +namespace base { + +namespace { +template <int N> class ElfClass { + public: + static const int kElfClass = -1; + static int ElfBind(const ElfW(Sym) *) { + CHECK(false); // << "Unexpected word size"; + return 0; + } + static int ElfType(const ElfW(Sym) *) { + CHECK(false); // << "Unexpected word size"; + return 0; + } +}; + +template <> class ElfClass<32> { + public: + static const int kElfClass = ELFCLASS32; + static int ElfBind(const ElfW(Sym) *symbol) { + return ELF32_ST_BIND(symbol->st_info); + } + static int ElfType(const ElfW(Sym) *symbol) { + return ELF32_ST_TYPE(symbol->st_info); + } +}; + +template <> class ElfClass<64> { + public: + static const int kElfClass = ELFCLASS64; + static int ElfBind(const ElfW(Sym) *symbol) { + return ELF64_ST_BIND(symbol->st_info); + } + static int ElfType(const ElfW(Sym) *symbol) { + return ELF64_ST_TYPE(symbol->st_info); + } +}; + +typedef ElfClass<__WORDSIZE> CurrentElfClass; + +// Extract an element from one of the ELF tables, cast it to desired type. +// This is just a simple arithmetic and a glorified cast. +// Callers are responsible for bounds checking. +template <class T> +const T* GetTableElement(const ElfW(Ehdr) *ehdr, + ElfW(Off) table_offset, + ElfW(Word) element_size, + size_t index) { + return reinterpret_cast<const T*>(reinterpret_cast<const char *>(ehdr) + + table_offset + + index * element_size); +} +} // namespace + +const void *const ElfMemImage::kInvalidBase = + reinterpret_cast<const void *>(~0L); + +ElfMemImage::ElfMemImage(const void *base) { + CHECK(base != kInvalidBase); + Init(base); +} + +int ElfMemImage::GetNumSymbols() const { + if (!hash_) { + return 0; + } + // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash + return hash_[1]; +} + +const ElfW(Sym) *ElfMemImage::GetDynsym(int index) const { + CHECK_LT(index, GetNumSymbols()); + return dynsym_ + index; +} + +const ElfW(Versym) *ElfMemImage::GetVersym(int index) const { + CHECK_LT(index, GetNumSymbols()); + return versym_ + index; +} + +const ElfW(Phdr) *ElfMemImage::GetPhdr(int index) const { + CHECK_LT(index, ehdr_->e_phnum); + return GetTableElement<ElfW(Phdr)>(ehdr_, + ehdr_->e_phoff, + ehdr_->e_phentsize, + index); +} + +const char *ElfMemImage::GetDynstr(ElfW(Word) offset) const { + CHECK_LT(offset, strsize_); + return dynstr_ + offset; +} + +const void *ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const { + if (sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE) { + // Symbol corresponds to "special" (e.g. SHN_ABS) section. + return reinterpret_cast<const void *>(sym->st_value); + } + CHECK_LT(link_base_, sym->st_value); + return GetTableElement<char>(ehdr_, 0, 1, sym->st_value) - link_base_; +} + +const ElfW(Verdef) *ElfMemImage::GetVerdef(int index) const { + CHECK_LE(index, verdefnum_); + const ElfW(Verdef) *version_definition = verdef_; + while (version_definition->vd_ndx < index && version_definition->vd_next) { + const char *const version_definition_as_char = + reinterpret_cast<const char *>(version_definition); + version_definition = + reinterpret_cast<const ElfW(Verdef) *>(version_definition_as_char + + version_definition->vd_next); + } + return version_definition->vd_ndx == index ? version_definition : NULL; +} + +const ElfW(Verdaux) *ElfMemImage::GetVerdefAux( + const ElfW(Verdef) *verdef) const { + return reinterpret_cast<const ElfW(Verdaux) *>(verdef+1); +} + +const char *ElfMemImage::GetVerstr(ElfW(Word) offset) const { + CHECK_LT(offset, strsize_); + return dynstr_ + offset; +} + +void ElfMemImage::Init(const void *base) { + ehdr_ = NULL; + dynsym_ = NULL; + dynstr_ = NULL; + versym_ = NULL; + verdef_ = NULL; + hash_ = NULL; + strsize_ = 0; + verdefnum_ = 0; + link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this. + if (!base) { + return; + } + const intptr_t base_as_uintptr_t = reinterpret_cast<uintptr_t>(base); + // Fake VDSO has low bit set. + const bool fake_vdso = ((base_as_uintptr_t & 1) != 0); + base = reinterpret_cast<const void *>(base_as_uintptr_t & ~1); + const char *const base_as_char = reinterpret_cast<const char *>(base); + if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 || + base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) { + RAW_DCHECK(false, "no ELF magic"); // at %p", base); + return; + } + int elf_class = base_as_char[EI_CLASS]; + if (elf_class != CurrentElfClass::kElfClass) { + DCHECK_EQ(elf_class, CurrentElfClass::kElfClass); + return; + } + switch (base_as_char[EI_DATA]) { + case ELFDATA2LSB: { + if (__LITTLE_ENDIAN != __BYTE_ORDER) { + DCHECK_EQ(__LITTLE_ENDIAN, __BYTE_ORDER); // << ": wrong byte order"; + return; + } + break; + } + case ELFDATA2MSB: { + if (__BIG_ENDIAN != __BYTE_ORDER) { + DCHECK_EQ(__BIG_ENDIAN, __BYTE_ORDER); // << ": wrong byte order"; + return; + } + break; + } + default: { + RAW_DCHECK(false, "unexpected data encoding"); // << base_as_char[EI_DATA]; + return; + } + } + + ehdr_ = reinterpret_cast<const ElfW(Ehdr) *>(base); + const ElfW(Phdr) *dynamic_program_header = NULL; + for (int i = 0; i < ehdr_->e_phnum; ++i) { + const ElfW(Phdr) *const program_header = GetPhdr(i); + switch (program_header->p_type) { + case PT_LOAD: + if (link_base_ == ~0L) { + link_base_ = program_header->p_vaddr; + } + break; + case PT_DYNAMIC: + dynamic_program_header = program_header; + break; + } + } + if (link_base_ == ~0L || !dynamic_program_header) { + RAW_DCHECK(~0L != link_base_, "no PT_LOADs in VDSO"); + RAW_DCHECK(dynamic_program_header, "no PT_DYNAMIC in VDSO"); + // Mark this image as not present. Can not recur infinitely. + Init(0); + return; + } + ptrdiff_t relocation = + base_as_char - reinterpret_cast<const char *>(link_base_); + ElfW(Dyn) *dynamic_entry = + reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr + + relocation); + for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) { + ElfW(Xword) value = dynamic_entry->d_un.d_val; + if (fake_vdso) { + // A complication: in the real VDSO, dynamic entries are not relocated + // (it wasn't loaded by a dynamic loader). But when testing with a + // "fake" dlopen()ed vdso library, the loader relocates some (but + // not all!) of them before we get here. + if (dynamic_entry->d_tag == DT_VERDEF) { + // The only dynamic entry (of the ones we care about) libc-2.3.6 + // loader doesn't relocate. + value += relocation; + } + } else { + // Real VDSO. Everything needs to be relocated. + value += relocation; + } + switch (dynamic_entry->d_tag) { + case DT_HASH: + hash_ = reinterpret_cast<ElfW(Word) *>(value); + break; + case DT_SYMTAB: + dynsym_ = reinterpret_cast<ElfW(Sym) *>(value); + break; + case DT_STRTAB: + dynstr_ = reinterpret_cast<const char *>(value); + break; + case DT_VERSYM: + versym_ = reinterpret_cast<ElfW(Versym) *>(value); + break; + case DT_VERDEF: + verdef_ = reinterpret_cast<ElfW(Verdef) *>(value); + break; + case DT_VERDEFNUM: + verdefnum_ = dynamic_entry->d_un.d_val; + break; + case DT_STRSZ: + strsize_ = dynamic_entry->d_un.d_val; + break; + default: + // Unrecognized entries explicitly ignored. + break; + } + } + if (!hash_ || !dynsym_ || !dynstr_ || !versym_ || + !verdef_ || !verdefnum_ || !strsize_) { + RAW_DCHECK(hash_, "invalid VDSO (no DT_HASH)"); + RAW_DCHECK(dynsym_, "invalid VDSO (no DT_SYMTAB)"); + RAW_DCHECK(dynstr_, "invalid VDSO (no DT_STRTAB)"); + RAW_DCHECK(versym_, "invalid VDSO (no DT_VERSYM)"); + RAW_DCHECK(verdef_, "invalid VDSO (no DT_VERDEF)"); + RAW_DCHECK(verdefnum_, "invalid VDSO (no DT_VERDEFNUM)"); + RAW_DCHECK(strsize_, "invalid VDSO (no DT_STRSZ)"); + // Mark this image as not present. Can not recur infinitely. + Init(0); + return; + } +} + +bool ElfMemImage::LookupSymbol(const char *name, + const char *version, + int type, + SymbolInfo *info) const { + for (SymbolIterator it = begin(); it != end(); ++it) { + if (strcmp(it->name, name) == 0 && strcmp(it->version, version) == 0 && + CurrentElfClass::ElfType(it->symbol) == type) { + if (info) { + *info = *it; + } + return true; + } + } + return false; +} + +bool ElfMemImage::LookupSymbolByAddress(const void *address, + SymbolInfo *info_out) const { + for (SymbolIterator it = begin(); it != end(); ++it) { + const char *const symbol_start = + reinterpret_cast<const char *>(it->address); + const char *const symbol_end = symbol_start + it->symbol->st_size; + if (symbol_start <= address && address < symbol_end) { + if (info_out) { + // Client wants to know details for that symbol (the usual case). + if (CurrentElfClass::ElfBind(it->symbol) == STB_GLOBAL) { + // Strong symbol; just return it. + *info_out = *it; + return true; + } else { + // Weak or local. Record it, but keep looking for a strong one. + *info_out = *it; + } + } else { + // Client only cares if there is an overlapping symbol. + return true; + } + } + } + return false; +} + +ElfMemImage::SymbolIterator::SymbolIterator(const void *const image, int index) + : index_(index), image_(image) { +} + +const ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator->() const { + return &info_; +} + +const ElfMemImage::SymbolInfo& ElfMemImage::SymbolIterator::operator*() const { + return info_; +} + +bool ElfMemImage::SymbolIterator::operator==(const SymbolIterator &rhs) const { + return this->image_ == rhs.image_ && this->index_ == rhs.index_; +} + +bool ElfMemImage::SymbolIterator::operator!=(const SymbolIterator &rhs) const { + return !(*this == rhs); +} + +ElfMemImage::SymbolIterator &ElfMemImage::SymbolIterator::operator++() { + this->Update(1); + return *this; +} + +ElfMemImage::SymbolIterator ElfMemImage::begin() const { + SymbolIterator it(this, 0); + it.Update(0); + return it; +} + +ElfMemImage::SymbolIterator ElfMemImage::end() const { + return SymbolIterator(this, GetNumSymbols()); +} + +void ElfMemImage::SymbolIterator::Update(int increment) { + const ElfMemImage *image = reinterpret_cast<const ElfMemImage *>(image_); + CHECK(image->IsPresent() || increment == 0); + if (!image->IsPresent()) { + return; + } + index_ += increment; + if (index_ >= image->GetNumSymbols()) { + index_ = image->GetNumSymbols(); + return; + } + const ElfW(Sym) *symbol = image->GetDynsym(index_); + const ElfW(Versym) *version_symbol = image->GetVersym(index_); + CHECK(symbol && version_symbol); + const char *const symbol_name = image->GetDynstr(symbol->st_name); + const ElfW(Versym) version_index = version_symbol[0] & VERSYM_VERSION; + const ElfW(Verdef) *version_definition = NULL; + const char *version_name = ""; + if (symbol->st_shndx == SHN_UNDEF) { + // Undefined symbols reference DT_VERNEED, not DT_VERDEF, and + // version_index could well be greater than verdefnum_, so calling + // GetVerdef(version_index) may trigger assertion. + } else { + version_definition = image->GetVerdef(version_index); + } + if (version_definition) { + // I am expecting 1 or 2 auxiliary entries: 1 for the version itself, + // optional 2nd if the version has a parent. + CHECK_LE(1, version_definition->vd_cnt); + CHECK_LE(version_definition->vd_cnt, 2); + const ElfW(Verdaux) *version_aux = image->GetVerdefAux(version_definition); + version_name = image->GetVerstr(version_aux->vda_name); + } + info_.name = symbol_name; + info_.version = version_name; + info_.address = image->GetSymAddr(symbol); + info_.symbol = symbol; +} + +} // namespace base + +#endif // HAVE_ELF_MEM_IMAGE diff --git a/third_party/tcmalloc/vendor/src/base/elf_mem_image.h b/third_party/tcmalloc/vendor/src/base/elf_mem_image.h new file mode 100644 index 0000000..6f1f097 --- /dev/null +++ b/third_party/tcmalloc/vendor/src/base/elf_mem_image.h @@ -0,0 +1,134 @@ +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Paul Pluzhnikov +// +// Allow dynamic symbol lookup for in-memory Elf images. + +#ifndef BASE_ELF_MEM_IMAGE_H_ +#define BASE_ELF_MEM_IMAGE_H_ + +#include <config.h> +#ifdef HAVE_FEATURES_H +#include <features.h> // for __GLIBC__ +#endif + +// Maybe one day we can rewrite this file not to require the elf +// symbol extensions in glibc, but for right now we need them. +#if defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) + +#define HAVE_ELF_MEM_IMAGE 1 + +#include <stdlib.h> +#include <link.h> // for ElfW + +namespace base { + +// An in-memory ELF image (may not exist on disk). +class ElfMemImage { + public: + // Sentinel: there could never be an elf image at this address. + static const void *const kInvalidBase; + + // Information about a single vdso symbol. + // All pointers are into .dynsym, .dynstr, or .text of the VDSO. + // Do not free() them or modify through them. + struct SymbolInfo { + const char *name; // E.g. "__vdso_getcpu" + const char *version; // E.g. "LINUX_2.6", could be "" + // for unversioned symbol. + const void *address; // Relocated symbol address. + const ElfW(Sym) *symbol; // Symbol in the dynamic symbol table. + }; + + // Supports iteration over all dynamic symbols. + class SymbolIterator { + public: + friend class ElfMemImage; + const SymbolInfo *operator->() const; + const SymbolInfo &operator*() const; + SymbolIterator& operator++(); + bool operator!=(const SymbolIterator &rhs) const; + bool operator==(const SymbolIterator &rhs) const; + private: + SymbolIterator(const void *const image, int index); + void Update(int incr); + SymbolInfo info_; + int index_; + const void *const image_; + }; + + + explicit ElfMemImage(const void *base); + void Init(const void *base); + bool IsPresent() const { return ehdr_ != NULL; } + const ElfW(Phdr)* GetPhdr(int index) const; + const ElfW(Sym)* GetDynsym(int index) const; + const ElfW(Versym)* GetVersym(int index) const; + const ElfW(Verdef)* GetVerdef(int index) const; + const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const; + const char* GetDynstr(ElfW(Word) offset) const; + const void* GetSymAddr(const ElfW(Sym) *sym) const; + const char* GetVerstr(ElfW(Word) offset) const; + int GetNumSymbols() const; + + SymbolIterator begin() const; + SymbolIterator end() const; + + // Look up versioned dynamic symbol in the image. + // Returns false if image is not present, or doesn't contain given + // symbol/version/type combination. + // If info_out != NULL, additional details are filled in. + bool LookupSymbol(const char *name, const char *version, + int symbol_type, SymbolInfo *info_out) const; + + // Find info about symbol (if any) which overlaps given address. + // Returns true if symbol was found; false if image isn't present + // or doesn't have a symbol overlapping given address. + // If info_out != NULL, additional details are filled in. + bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const; + + private: + const ElfW(Ehdr) *ehdr_; + const ElfW(Sym) *dynsym_; + const ElfW(Versym) *versym_; + const ElfW(Verdef) *verdef_; + const ElfW(Word) *hash_; + const char *dynstr_; + size_t strsize_; + size_t verdefnum_; + ElfW(Addr) link_base_; // Link-time base (p_vaddr of first PT_LOAD). +}; + +} // namespace base + +#endif // __ELF__ and __GLIBC__ and !__native_client__ + +#endif // BASE_ELF_MEM_IMAGE_H_ diff --git a/third_party/tcmalloc/vendor/src/base/low_level_alloc.cc b/third_party/tcmalloc/vendor/src/base/low_level_alloc.cc index 532c594..70f510d6 100644 --- a/third_party/tcmalloc/vendor/src/base/low_level_alloc.cc +++ b/third_party/tcmalloc/vendor/src/base/low_level_alloc.cc @@ -233,7 +233,7 @@ namespace { this->arena_->mu.Lock(); } ~ArenaLock() { RAW_CHECK(this->left_, "haven't left Arena region"); } - void Leave() UNLOCK_FUNCTION() { + void Leave() /*UNLOCK_FUNCTION()*/ { this->arena_->mu.Unlock(); #if 0 if (this->mask_valid_) { diff --git a/third_party/tcmalloc/vendor/src/base/spinlock_internal.cc b/third_party/tcmalloc/vendor/src/base/spinlock_internal.cc index b5b6ca4..7bd0e21 100644 --- a/third_party/tcmalloc/vendor/src/base/spinlock_internal.cc +++ b/third_party/tcmalloc/vendor/src/base/spinlock_internal.cc @@ -44,7 +44,7 @@ #if defined(_WIN32) #include "base/spinlock_win32-inl.h" -#elif defined(__linux__) +#elif defined(__linux__) && !defined(__native_client__) #include "base/spinlock_linux-inl.h" #else #include "base/spinlock_posix-inl.h" diff --git a/third_party/tcmalloc/vendor/src/base/vdso_support.cc b/third_party/tcmalloc/vendor/src/base/vdso_support.cc index 09288a5..767ee5f 100644 --- a/third_party/tcmalloc/vendor/src/base/vdso_support.cc +++ b/third_party/tcmalloc/vendor/src/base/vdso_support.cc @@ -54,285 +54,14 @@ using base::subtle::MemoryBarrier; #define AT_SYSINFO_EHDR 33 #endif -// From binutils/include/elf/common.h (this doesn't appear to be documented -// anywhere else). -// -// /* This flag appears in a Versym structure. It means that the symbol -// is hidden, and is only visible with an explicit version number. -// This is a GNU extension. */ -// #define VERSYM_HIDDEN 0x8000 -// -// /* This is the mask for the rest of the Versym information. */ -// #define VERSYM_VERSION 0x7fff - -#define VERSYM_VERSION 0x7fff - namespace base { -namespace { -template <int N> class ElfClass { - public: - static const int kElfClass = -1; - static int ElfBind(const ElfW(Sym) *) { - CHECK(false); // << "Unexpected word size"; - return 0; - } - static int ElfType(const ElfW(Sym) *) { - CHECK(false); // << "Unexpected word size"; - return 0; - } -}; - -template <> class ElfClass<32> { - public: - static const int kElfClass = ELFCLASS32; - static int ElfBind(const ElfW(Sym) *symbol) { - return ELF32_ST_BIND(symbol->st_info); - } - static int ElfType(const ElfW(Sym) *symbol) { - return ELF32_ST_TYPE(symbol->st_info); - } -}; - -template <> class ElfClass<64> { - public: - static const int kElfClass = ELFCLASS64; - static int ElfBind(const ElfW(Sym) *symbol) { - return ELF64_ST_BIND(symbol->st_info); - } - static int ElfType(const ElfW(Sym) *symbol) { - return ELF64_ST_TYPE(symbol->st_info); - } -}; - -typedef ElfClass<__WORDSIZE> CurrentElfClass; - -// Extract an element from one of the ELF tables, cast it to desired type. -// This is just a simple arithmetic and a glorified cast. -// Callers are responsible for bounds checking. -template <class T> -const T* GetTableElement(const ElfW(Ehdr) *ehdr, - ElfW(Off) table_offset, - ElfW(Word) element_size, - size_t index) { - return reinterpret_cast<const T*>(reinterpret_cast<const char *>(ehdr) - + table_offset - + index * element_size); -} -} // namespace - -const void *const VDSOSupport::kInvalidBase = - reinterpret_cast<const void *>(~0L); - -const void *VDSOSupport::vdso_base_ = kInvalidBase; +const void *VDSOSupport::vdso_base_ = ElfMemImage::kInvalidBase; VDSOSupport::GetCpuFn VDSOSupport::getcpu_fn_ = &InitAndGetCPU; - -VDSOSupport::ElfMemImage::ElfMemImage(const void *base) { - CHECK(base != kInvalidBase); - Init(base); -} - -int VDSOSupport::ElfMemImage::GetNumSymbols() const { - if (!hash_) { - return 0; - } - // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash - return hash_[1]; -} - -const ElfW(Sym) *VDSOSupport::ElfMemImage::GetDynsym(int index) const { - CHECK_LT(index, GetNumSymbols()); - return dynsym_ + index; -} - -const ElfW(Versym) *VDSOSupport::ElfMemImage::GetVersym(int index) const { - CHECK_LT(index, GetNumSymbols()); - return versym_ + index; -} - -const ElfW(Phdr) *VDSOSupport::ElfMemImage::GetPhdr(int index) const { - CHECK_LT(index, ehdr_->e_phnum); - return GetTableElement<ElfW(Phdr)>(ehdr_, - ehdr_->e_phoff, - ehdr_->e_phentsize, - index); -} - -const char *VDSOSupport::ElfMemImage::GetDynstr(ElfW(Word) offset) const { - CHECK_LT(offset, strsize_); - return dynstr_ + offset; -} - -const void *VDSOSupport::ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const { - if (sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE) { - // Symbol corresponds to "special" (e.g. SHN_ABS) section. - return reinterpret_cast<const void *>(sym->st_value); - } - CHECK_LT(link_base_, sym->st_value); - return GetTableElement<char>(ehdr_, 0, 1, sym->st_value) - link_base_; -} - -const ElfW(Verdef) *VDSOSupport::ElfMemImage::GetVerdef(int index) const { - CHECK_LE(index, verdefnum_); - const ElfW(Verdef) *version_definition = verdef_; - while (version_definition->vd_ndx < index && version_definition->vd_next) { - const char *const version_definition_as_char = - reinterpret_cast<const char *>(version_definition); - version_definition = - reinterpret_cast<const ElfW(Verdef) *>(version_definition_as_char + - version_definition->vd_next); - } - return version_definition->vd_ndx == index ? version_definition : NULL; -} - -const ElfW(Verdaux) *VDSOSupport::ElfMemImage::GetVerdefAux( - const ElfW(Verdef) *verdef) const { - return reinterpret_cast<const ElfW(Verdaux) *>(verdef+1); -} - -const char *VDSOSupport::ElfMemImage::GetVerstr(ElfW(Word) offset) const { - CHECK_LT(offset, strsize_); - return dynstr_ + offset; -} - -void VDSOSupport::ElfMemImage::Init(const void *base) { - ehdr_ = NULL; - dynsym_ = NULL; - dynstr_ = NULL; - versym_ = NULL; - verdef_ = NULL; - hash_ = NULL; - strsize_ = 0; - verdefnum_ = 0; - link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this. - if (!base) { - return; - } - const intptr_t base_as_uintptr_t = reinterpret_cast<uintptr_t>(base); - // Fake VDSO has low bit set. - const bool fake_vdso = ((base_as_uintptr_t & 1) != 0); - base = reinterpret_cast<const void *>(base_as_uintptr_t & ~1); - const char *const base_as_char = reinterpret_cast<const char *>(base); - if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 || - base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) { - RAW_DCHECK(false, "no ELF magic"); // at %p", base); - return; - } - int elf_class = base_as_char[EI_CLASS]; - if (elf_class != CurrentElfClass::kElfClass) { - DCHECK_EQ(elf_class, CurrentElfClass::kElfClass); - return; - } - switch (base_as_char[EI_DATA]) { - case ELFDATA2LSB: { - if (__LITTLE_ENDIAN != __BYTE_ORDER) { - DCHECK_EQ(__LITTLE_ENDIAN, __BYTE_ORDER); // << ": wrong byte order"; - return; - } - break; - } - case ELFDATA2MSB: { - if (__BIG_ENDIAN != __BYTE_ORDER) { - DCHECK_EQ(__BIG_ENDIAN, __BYTE_ORDER); // << ": wrong byte order"; - return; - } - break; - } - default: { - RAW_DCHECK(false, "unexpected data encoding"); // << base_as_char[EI_DATA]; - return; - } - } - - ehdr_ = reinterpret_cast<const ElfW(Ehdr) *>(base); - const ElfW(Phdr) *dynamic_program_header = NULL; - for (int i = 0; i < ehdr_->e_phnum; ++i) { - const ElfW(Phdr) *const program_header = GetPhdr(i); - switch (program_header->p_type) { - case PT_LOAD: - if (link_base_ == ~0L) { - link_base_ = program_header->p_vaddr; - } - break; - case PT_DYNAMIC: - dynamic_program_header = program_header; - break; - } - } - if (link_base_ == ~0L || !dynamic_program_header) { - RAW_DCHECK(~0L != link_base_, "no PT_LOADs in VDSO"); - RAW_DCHECK(dynamic_program_header, "no PT_DYNAMIC in VDSO"); - // Mark this image as not present. Can not recur infinitely. - Init(0); - return; - } - ptrdiff_t relocation = - base_as_char - reinterpret_cast<const char *>(link_base_); - ElfW(Dyn) *dynamic_entry = - reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr + - relocation); - for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) { - ElfW(Xword) value = dynamic_entry->d_un.d_val; - if (fake_vdso) { - // A complication: in the real VDSO, dynamic entries are not relocated - // (it wasn't loaded by a dynamic loader). But when testing with a - // "fake" dlopen()ed vdso library, the loader relocates some (but - // not all!) of them before we get here. - if (dynamic_entry->d_tag == DT_VERDEF) { - // The only dynamic entry (of the ones we care about) libc-2.3.6 - // loader doesn't relocate. - value += relocation; - } - } else { - // Real VDSO. Everything needs to be relocated. - value += relocation; - } - switch (dynamic_entry->d_tag) { - case DT_HASH: - hash_ = reinterpret_cast<ElfW(Word) *>(value); - break; - case DT_SYMTAB: - dynsym_ = reinterpret_cast<ElfW(Sym) *>(value); - break; - case DT_STRTAB: - dynstr_ = reinterpret_cast<const char *>(value); - break; - case DT_VERSYM: - versym_ = reinterpret_cast<ElfW(Versym) *>(value); - break; - case DT_VERDEF: - verdef_ = reinterpret_cast<ElfW(Verdef) *>(value); - break; - case DT_VERDEFNUM: - verdefnum_ = dynamic_entry->d_un.d_val; - break; - case DT_STRSZ: - strsize_ = dynamic_entry->d_un.d_val; - break; - default: - // Unrecognized entries explicitly ignored. - break; - } - } - if (!hash_ || !dynsym_ || !dynstr_ || !versym_ || - !verdef_ || !verdefnum_ || !strsize_) { - RAW_DCHECK(hash_, "invalid VDSO (no DT_HASH)"); - RAW_DCHECK(dynsym_, "invalid VDSO (no DT_SYMTAB)"); - RAW_DCHECK(dynstr_, "invalid VDSO (no DT_STRTAB)"); - RAW_DCHECK(versym_, "invalid VDSO (no DT_VERSYM)"); - RAW_DCHECK(verdef_, "invalid VDSO (no DT_VERDEF)"); - RAW_DCHECK(verdefnum_, "invalid VDSO (no DT_VERDEFNUM)"); - RAW_DCHECK(strsize_, "invalid VDSO (no DT_STRSZ)"); - // Mark this image as not present. Can not recur infinitely. - Init(0); - return; - } -} - VDSOSupport::VDSOSupport() // If vdso_base_ is still set to kInvalidBase, we got here // before VDSOSupport::Init has been called. Call it now. - : image_(vdso_base_ == kInvalidBase ? Init() : vdso_base_) { + : image_(vdso_base_ == ElfMemImage::kInvalidBase ? Init() : vdso_base_) { } // NOTE: we can't use GoogleOnceInit() below, because we can be @@ -345,7 +74,7 @@ VDSOSupport::VDSOSupport() // Finally, even if there is a race here, it is harmless, because // the operation should be idempotent. const void *VDSOSupport::Init() { - if (vdso_base_ == kInvalidBase) { + if (vdso_base_ == ElfMemImage::kInvalidBase) { // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[] // on stack, and so glibc works as if VDSO was not present. // But going directly to kernel via /proc/self/auxv below bypasses @@ -372,7 +101,7 @@ const void *VDSOSupport::Init() { } } close(fd); - if (vdso_base_ == kInvalidBase) { + if (vdso_base_ == ElfMemImage::kInvalidBase) { // Didn't find AT_SYSINFO_EHDR in auxv[]. vdso_base_ = NULL; } @@ -395,6 +124,7 @@ const void *VDSOSupport::Init() { } const void *VDSOSupport::SetBase(const void *base) { + CHECK(base != ElfMemImage::kInvalidBase); const void *old_base = vdso_base_; vdso_base_ = base; image_.Init(base); @@ -407,116 +137,12 @@ bool VDSOSupport::LookupSymbol(const char *name, const char *version, int type, SymbolInfo *info) const { - for (SymbolIterator it = begin(); it != end(); ++it) { - if (strcmp(it->name, name) == 0 && strcmp(it->version, version) == 0 && - CurrentElfClass::ElfType(it->symbol) == type) { - if (info) { - *info = *it; - } - return true; - } - } - return false; + return image_.LookupSymbol(name, version, type, info); } bool VDSOSupport::LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const { - for (SymbolIterator it = begin(); it != end(); ++it) { - const char *const symbol_start = - reinterpret_cast<const char *>(it->address); - const char *const symbol_end = symbol_start + it->symbol->st_size; - if (symbol_start <= address && address < symbol_end) { - if (info_out) { - // Client wants to know details for that symbol (the usual case). - if (CurrentElfClass::ElfBind(it->symbol) == STB_GLOBAL) { - // Strong symbol; just return it. - *info_out = *it; - return true; - } else { - // Weak or local. Record it, but keep looking for a strong one. - *info_out = *it; - } - } else { - // Client only cares if there is an overlapping symbol. - return true; - } - } - } - return false; -} - -VDSOSupport::SymbolIterator::SymbolIterator(const void *const image, int index) - : index_(index), image_(image) { -} - -const VDSOSupport::SymbolInfo *VDSOSupport::SymbolIterator::operator->() const { - return &info_; -} - -const VDSOSupport::SymbolInfo& VDSOSupport::SymbolIterator::operator*() const { - return info_; -} - -bool VDSOSupport::SymbolIterator::operator==(const SymbolIterator &rhs) const { - return this->image_ == rhs.image_ && this->index_ == rhs.index_; -} - -bool VDSOSupport::SymbolIterator::operator!=(const SymbolIterator &rhs) const { - return !(*this == rhs); -} - -VDSOSupport::SymbolIterator &VDSOSupport::SymbolIterator::operator++() { - this->Update(1); - return *this; -} - -VDSOSupport::SymbolIterator VDSOSupport::begin() const { - SymbolIterator it(&image_, 0); - it.Update(0); - return it; -} - -VDSOSupport::SymbolIterator VDSOSupport::end() const { - return SymbolIterator(&image_, image_.GetNumSymbols()); -} - -void VDSOSupport::SymbolIterator::Update(int increment) { - const ElfMemImage *image = reinterpret_cast<const ElfMemImage *>(image_); - CHECK(image->IsPresent() || increment == 0); - if (!image->IsPresent()) { - return; - } - index_ += increment; - if (index_ >= image->GetNumSymbols()) { - index_ = image->GetNumSymbols(); - return; - } - const ElfW(Sym) *symbol = image->GetDynsym(index_); - const ElfW(Versym) *version_symbol = image->GetVersym(index_); - CHECK(symbol && version_symbol); - const char *const symbol_name = image->GetDynstr(symbol->st_name); - const ElfW(Versym) version_index = version_symbol[0] & VERSYM_VERSION; - const ElfW(Verdef) *version_definition = NULL; - const char *version_name = ""; - if (symbol->st_shndx == SHN_UNDEF) { - // Undefined symbols reference DT_VERNEED, not DT_VERDEF, and - // version_index could well be greater than verdefnum_, so calling - // GetVerdef(version_index) may trigger assertion. - } else { - version_definition = image->GetVerdef(version_index); - } - if (version_definition) { - // I am expecting 1 or 2 auxiliary entries: 1 for the version itself, - // optional 2nd if the version has a parent. - CHECK_LE(1, version_definition->vd_cnt); - CHECK_LE(version_definition->vd_cnt, 2); - const ElfW(Verdaux) *version_aux = image->GetVerdefAux(version_definition); - version_name = image->GetVerstr(version_aux->vda_name); - } - info_.name = symbol_name; - info_.version = version_name; - info_.address = image->GetSymAddr(symbol); - info_.symbol = symbol; + return image_.LookupSymbolByAddress(address, info_out); } // NOLINT on 'long' because this routine mimics kernel api. diff --git a/third_party/tcmalloc/vendor/src/base/vdso_support.h b/third_party/tcmalloc/vendor/src/base/vdso_support.h index 131646a..b97ab25 100644 --- a/third_party/tcmalloc/vendor/src/base/vdso_support.h +++ b/third_party/tcmalloc/vendor/src/base/vdso_support.h @@ -1,5 +1,34 @@ -// Copyright 2008 Google Inc. All Rights Reserved. -// Author: ppluzhnikov@google.com (Paul Pluzhnikov) +// Copyright (c) 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Paul Pluzhnikov // // Allow dynamic symbol lookup in the kernel VDSO page. // @@ -27,19 +56,14 @@ #define BASE_VDSO_SUPPORT_H_ #include <config.h> -#ifdef HAVE_FEATURES_H -#include <features.h> // for __GLIBC__ -#endif #include "base/basictypes.h" +#include "base/elf_mem_image.h" -// Maybe one day we can rewrite this file not to require the elf -// symbol extensions in glibc, but for right now we need them. -#if defined(__ELF__) && defined(__GLIBC__) +#ifdef HAVE_ELF_MEM_IMAGE #define HAVE_VDSO_SUPPORT 1 #include <stdlib.h> // for NULL -#include <link.h> // for ElfW namespace base { @@ -47,45 +71,17 @@ namespace base { // use any memory allocation routines. class VDSOSupport { public: - // Sentinel: there could never be a VDSO at this address. - static const void *const kInvalidBase; - - // Information about a single vdso symbol. - // All pointers are into .dynsym, .dynstr, or .text of the VDSO. - // Do not free() them or modify through them. - struct SymbolInfo { - const char *name; // E.g. "__vdso_getcpu" - const char *version; // E.g. "LINUX_2.6", could be "" - // for unversioned symbol. - const void *address; // Relocated symbol address. - const ElfW(Sym) *symbol; // Symbol in the dynamic symbol table. - }; - - // Supports iteration over all dynamic symbols. - class SymbolIterator { - public: - friend class VDSOSupport; - const SymbolInfo *operator->() const; - const SymbolInfo &operator*() const; - SymbolIterator& operator++(); - bool operator!=(const SymbolIterator &rhs) const; - bool operator==(const SymbolIterator &rhs) const; - private: - SymbolIterator(const void *const image, int index); - void Update(int incr); - SymbolInfo info_; - int index_; - const void *const image_; - }; - VDSOSupport(); + typedef ElfMemImage::SymbolInfo SymbolInfo; + typedef ElfMemImage::SymbolIterator SymbolIterator; + // Answers whether we have a vdso at all. bool IsPresent() const { return image_.IsPresent(); } // Allow to iterate over all VDSO symbols. - SymbolIterator begin() const; - SymbolIterator end() const; + SymbolIterator begin() const { return image_.begin(); } + SymbolIterator end() const { return image_.end(); } // Look up versioned dynamic symbol in the kernel VDSO. // Returns false if VDSO is not present, or doesn't contain given @@ -111,33 +107,6 @@ class VDSOSupport { static const void *Init(); private: - // An in-memory ELF image (may not exist on disk). - class ElfMemImage { - public: - explicit ElfMemImage(const void *base); - void Init(const void *base); - bool IsPresent() const { return ehdr_ != NULL; } - const ElfW(Phdr)* GetPhdr(int index) const; - const ElfW(Sym)* GetDynsym(int index) const; - const ElfW(Versym)* GetVersym(int index) const; - const ElfW(Verdef)* GetVerdef(int index) const; - const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const; - const char* GetDynstr(ElfW(Word) offset) const; - const void* GetSymAddr(const ElfW(Sym) *sym) const; - const char* GetVerstr(ElfW(Word) offset) const; - int GetNumSymbols() const; - private: - const ElfW(Ehdr) *ehdr_; - const ElfW(Sym) *dynsym_; - const ElfW(Versym) *versym_; - const ElfW(Verdef) *verdef_; - const ElfW(Word) *hash_; - const char *dynstr_; - size_t strsize_; - size_t verdefnum_; - ElfW(Addr) link_base_; // Link-time base (p_vaddr of first PT_LOAD). - }; - // image_ represents VDSO ELF image in memory. // image_.ehdr_ == NULL implies there is no VDSO. ElfMemImage image_; @@ -181,6 +150,6 @@ class VDSOSupport { int GetCPU(); } // namespace base -#endif // __ELF__ and __GLIBC__ +#endif // HAVE_ELF_MEM_IMAGE #endif // BASE_VDSO_SUPPORT_H_ diff --git a/third_party/tcmalloc/vendor/src/central_freelist.cc b/third_party/tcmalloc/vendor/src/central_freelist.cc index 6b3be06..9b20cf8 100644 --- a/third_party/tcmalloc/vendor/src/central_freelist.cc +++ b/third_party/tcmalloc/vendor/src/central_freelist.cc @@ -31,29 +31,51 @@ // Author: Sanjay Ghemawat <opensource@google.com> #include "config.h" +#include <algorithm> #include "central_freelist.h" - #include "internal_logging.h" // for ASSERT, MESSAGE #include "linked_list.h" // for SLL_Next, SLL_Push, etc #include "page_heap.h" // for PageHeap #include "static_vars.h" // for Static +using std::min; +using std::max; + namespace tcmalloc { void CentralFreeList::Init(size_t cl) { size_class_ = cl; tcmalloc::DLL_Init(&empty_); tcmalloc::DLL_Init(&nonempty_); + num_spans_ = 0; counter_ = 0; + max_cache_size_ = kMaxNumTransferEntries; #ifdef TCMALLOC_SMALL_BUT_SLOW // Disable the transfer cache for the small footprint case. cache_size_ = 0; #else cache_size_ = 16; #endif + if (cl > 0) { + // Limit the maximum size of the cache based on the size class. If this + // is not done, large size class objects will consume a lot of memory if + // they just sit in the transfer cache. + int32_t bytes = Static::sizemap()->ByteSizeForClass(cl); + int32_t objs_to_move = Static::sizemap()->num_objects_to_move(cl); + + ASSERT(objs_to_move > 0 && bytes > 0); + // Limit each size class cache to at most 1MB of objects or one entry, + // whichever is greater. Total transfer cache memory used across all + // size classes then can't be greater than approximately + // 1MB * kMaxNumTransferEntries. + // min and max are in parens to avoid macro-expansion on windows. + max_cache_size_ = (min)(max_cache_size_, + (max)(1, (1024 * 1024) / (bytes * objs_to_move))); + cache_size_ = (min)(cache_size_, max_cache_size_); + } used_slots_ = 0; - ASSERT(cache_size_ <= kNumTransferEntries); + ASSERT(cache_size_ <= max_cache_size_); } void CentralFreeList::ReleaseListToSpans(void* start) { @@ -110,6 +132,7 @@ void CentralFreeList::ReleaseToSpans(void* object) { counter_ -= ((span->length<<kPageShift) / Static::sizemap()->ByteSizeForClass(span->sizeclass)); tcmalloc::DLL_Remove(span); + --num_spans_; // Release central list lock while operating on pageheap lock_.Unlock(); @@ -144,7 +167,7 @@ bool CentralFreeList::MakeCacheSpace() { // Is there room in the cache? if (used_slots_ < cache_size_) return true; // Check if we can expand this cache? - if (cache_size_ == kNumTransferEntries) return false; + if (cache_size_ == max_cache_size_) return false; // Ok, we'll try to grab an entry from some other size class. if (EvictRandomSizeClass(size_class_, false) || EvictRandomSizeClass(size_class_, true)) { @@ -153,7 +176,7 @@ bool CentralFreeList::MakeCacheSpace() { // EvictRandomSizeClass (via ShrinkCache and the LockInverter), so the // cache_size may have changed. Therefore, check and verify that it is // still OK to increase the cache_size. - if (cache_size_ < kNumTransferEntries) { + if (cache_size_ < max_cache_size_) { cache_size_++; return true; } @@ -210,7 +233,7 @@ void CentralFreeList::InsertRange(void *start, void *end, int N) { MakeCacheSpace()) { int slot = used_slots_++; ASSERT(slot >=0); - ASSERT(slot < kNumTransferEntries); + ASSERT(slot < max_cache_size_); TCEntry *entry = &tc_slots_[slot]; entry->head = start; entry->tail = end; @@ -328,6 +351,7 @@ void CentralFreeList::Populate() { // Add span to list of non-empty spans lock_.Lock(); tcmalloc::DLL_Prepend(&nonempty_, span); + ++num_spans_; counter_ += num; } @@ -336,4 +360,16 @@ int CentralFreeList::tc_length() { return used_slots_ * Static::sizemap()->num_objects_to_move(size_class_); } +size_t CentralFreeList::OverheadBytes() { + SpinLockHolder h(&lock_); + if (size_class_ == 0) { // 0 holds the 0-sized allocations + return 0; + } + const size_t pages_per_span = Static::sizemap()->class_to_pages(size_class_); + const size_t object_size = Static::sizemap()->class_to_size(size_class_); + ASSERT(object_size > 0); + const size_t overhead_per_span = (pages_per_span * kPageSize) % object_size; + return num_spans_ * overhead_per_span; +} + } // namespace tcmalloc diff --git a/third_party/tcmalloc/vendor/src/central_freelist.h b/third_party/tcmalloc/vendor/src/central_freelist.h index 69a09af..27e9d35 100644 --- a/third_party/tcmalloc/vendor/src/central_freelist.h +++ b/third_party/tcmalloc/vendor/src/central_freelist.h @@ -35,7 +35,9 @@ #include "config.h" #include <stddef.h> // for size_t +#ifdef HAVE_STDINT_H #include <stdint.h> // for int32_t +#endif #include "base/spinlock.h" #include "base/thread_annotations.h" #include "common.h" @@ -66,6 +68,12 @@ class CentralFreeList { // Returns the number of free objects in the transfer cache. int tc_length(); + // Returns the memory overhead (internal fragmentation) attributable + // to the freelist. This is memory lost when the size of elements + // in a freelist doesn't exactly divide the page-size (an 8192-byte + // page full of 5-byte objects would have 2 bytes memory overhead). + size_t OverheadBytes(); + private: // TransferCache is used to cache transfers of // sizemap.num_objects_to_move(size_class) back and forth between @@ -75,16 +83,16 @@ class CentralFreeList { void *tail; // Tail of chain of objects. }; - // A central cache freelist can have anywhere from 0 to kNumTransferEntries - // slots to put link list chains into. To keep memory usage bounded the total - // number of TCEntries across size classes is fixed. Currently each size - // class is initially given one TCEntry which also means that the maximum any - // one class can have is kNumClasses. + // A central cache freelist can have anywhere from 0 to kMaxNumTransferEntries + // slots to put link list chains into. #ifdef TCMALLOC_SMALL_BUT_SLOW // For the small memory model, the transfer cache is not used. - static const int kNumTransferEntries = 0; + static const int kMaxNumTransferEntries = 0; #else - static const int kNumTransferEntries = kNumClasses; + // Starting point for the the maximum number of entries in the transfer cache. + // This actual maximum for a given size class may be lower than this + // maximum value. + static const int kMaxNumTransferEntries = 64; #endif // REQUIRES: lock_ is held @@ -143,12 +151,15 @@ class CentralFreeList { size_t size_class_; // My size class Span empty_; // Dummy header for list of empty spans Span nonempty_; // Dummy header for list of non-empty spans + size_t num_spans_; // Number of spans in empty_ plus nonempty_ size_t counter_; // Number of free objects in cache entry - // Here we reserve space for TCEntry cache slots. Since one size class can - // end up getting all the TCEntries quota in the system we just preallocate - // sufficient number of entries here. - TCEntry tc_slots_[kNumTransferEntries]; + // Here we reserve space for TCEntry cache slots. Space is preallocated + // for the largest possible number of entries than any one size class may + // accumulate. Not all size classes are allowed to accumulate + // kMaxNumTransferEntries, so there is some wasted space for those size + // classes. + TCEntry tc_slots_[kMaxNumTransferEntries]; // Number of currently used cached entries in tc_slots_. This variable is // updated under a lock but can be read without one. @@ -157,6 +168,8 @@ class CentralFreeList { // adaptive value that is increased if there is lots of traffic // on a given size class. int32_t cache_size_; + // Maximum size of the cache for a given size class. + int32_t max_cache_size_; }; // Pads each CentralCache object to multiple of 64 bytes. Since some diff --git a/third_party/tcmalloc/vendor/src/common.cc b/third_party/tcmalloc/vendor/src/common.cc index 8221b08..90e6626 100644 --- a/third_party/tcmalloc/vendor/src/common.cc +++ b/third_party/tcmalloc/vendor/src/common.cc @@ -54,9 +54,9 @@ static inline int LgFloor(size_t n) { int AlignmentForSize(size_t size) { int alignment = kAlignment; - if (size >= 2048) { - // Cap alignment at 256 for large sizes. - alignment = 256; + if (size > kMaxSize) { + // Cap alignment at kPageSize for large sizes. + alignment = kPageSize; } else if (size >= 128) { // Space wasted due to alignment is at most 1/8, i.e., 12.5%. alignment = (1 << LgFloor(size)) / 8; @@ -65,6 +65,10 @@ int AlignmentForSize(size_t size) { // requirements for some SSE types. alignment = 16; } + // Maximum alignment allowed is page size alignment. + if (alignment > kPageSize) { + alignment = kPageSize; + } CHECK_CONDITION(size < 16 || alignment >= 16); CHECK_CONDITION((alignment & (alignment - 1)) == 0); return alignment; @@ -105,22 +109,23 @@ void SizeMap::Init() { int sc = 1; // Next size class to assign int alignment = kAlignment; CHECK_CONDITION(kAlignment <= 16); - int last_lg = -1; for (size_t size = kAlignment; size <= kMaxSize; size += alignment) { - int lg = LgFloor(size); - if (lg > last_lg) { - // Increase alignment every so often to reduce number of size classes. - alignment = AlignmentForSize(size); - last_lg = lg; - } + alignment = AlignmentForSize(size); CHECK_CONDITION((size % alignment) == 0); - // Allocate enough pages so leftover is less than 1/8 of total. - // This bounds wasted space to at most 12.5%. - size_t psize = kPageSize; - while ((psize % size) > (psize >> 3)) { + int blocks_to_move = NumMoveSize(size) / 4; + size_t psize = 0; + do { psize += kPageSize; - } + // Allocate enough pages so leftover is less than 1/8 of total. + // This bounds wasted space to at most 12.5%. + while ((psize % size) > (psize >> 3)) { + psize += kPageSize; + } + // Continue to add pages until there are at least as many objects in + // the span as are needed when moving objects from the central + // freelists and spans to the thread caches. + } while ((psize / size) < (blocks_to_move)); const size_t my_pages = psize >> kPageShift; if (sc > 1 && my_pages == class_to_pages_[sc-1]) { diff --git a/third_party/tcmalloc/vendor/src/common.h b/third_party/tcmalloc/vendor/src/common.h index e960c57..72725ca 100644 --- a/third_party/tcmalloc/vendor/src/common.h +++ b/third_party/tcmalloc/vendor/src/common.h @@ -63,16 +63,15 @@ typedef uintptr_t Length; #if defined(TCMALLOC_LARGE_PAGES) static const size_t kPageShift = 15; -static const size_t kNumClasses = 95; -static const size_t kMaxThreadCacheSize = 4 << 20; +static const size_t kNumClasses = 78; #else -static const size_t kPageShift = 12; -static const size_t kNumClasses = 61; -static const size_t kMaxThreadCacheSize = 2 << 20; +static const size_t kPageShift = 13; +static const size_t kNumClasses = 86; #endif +static const size_t kMaxThreadCacheSize = 4 << 20; static const size_t kPageSize = 1 << kPageShift; -static const size_t kMaxSize = 8u * kPageSize; +static const size_t kMaxSize = 256 * 1024; static const size_t kAlignment = 8; static const size_t kLargeSizeClass = 0; // For all span-lengths < kMaxPages we keep an exact-size list. @@ -166,7 +165,7 @@ class SizeMap { // 32768 (32768 + 127 + (120<<7)) / 128 376 static const int kMaxSmallSize = 1024; static const size_t kClassArraySize = - (((1 << kPageShift) * 8u + 127 + (120 << 7)) >> 7) + 1; + ((kMaxSize + 127 + (120 << 7)) >> 7) + 1; unsigned char class_array_[kClassArraySize]; // Compute index of the class_array[] entry for a given size diff --git a/third_party/tcmalloc/vendor/src/config.h.in b/third_party/tcmalloc/vendor/src/config.h.in index 9112951..64766ff 100644 --- a/third_party/tcmalloc/vendor/src/config.h.in +++ b/third_party/tcmalloc/vendor/src/config.h.in @@ -189,6 +189,9 @@ */ #undef LT_OBJDIR +/* Define to 'volatile' if __malloc_hook is declared volatile */ +#undef MALLOC_HOOK_MAYBE_VOLATILE + /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O @@ -232,6 +235,12 @@ /* printf format code for printing a size_t and ssize_t */ #undef PRIxS +/* Mark the systems where we know it's bad if pthreads runs too + early before main (before threads are initialized, presumably). */ +#ifdef __FreeBSD__ +#define PTHREADS_CRASHES_IF_RUN_TOO_EARLY 1 +#endif + /* Define to necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE diff --git a/third_party/tcmalloc/vendor/src/debugallocation.cc b/third_party/tcmalloc/vendor/src/debugallocation.cc index 9de927a..7cac751 100644 --- a/third_party/tcmalloc/vendor/src/debugallocation.cc +++ b/third_party/tcmalloc/vendor/src/debugallocation.cc @@ -134,13 +134,13 @@ static void TracePrintf(int fd, const char *fmt, ...) // The do_* functions are defined in tcmalloc/tcmalloc.cc, // which is included before this file // when TCMALLOC_FOR_DEBUGALLOCATION is defined -#define BASE_MALLOC_NEW(size) cpp_alloc(size, false) +// TODO(csilvers): get rid of these now that we are tied to tcmalloc. +#define BASE_MALLOC_NEW do_malloc #define BASE_MALLOC do_malloc #define BASE_FREE do_free #define BASE_MALLOC_STATS do_malloc_stats #define BASE_MALLOPT do_mallopt #define BASE_MALLINFO do_mallinfo -#define BASE_MALLOC_SIZE(ptr) GetSizeWithCallback(ptr, &InvalidGetAllocatedSize) // ========================================================================= // @@ -995,14 +995,25 @@ class DebugMallocImplementation : public TCMallocImplementation { return MallocBlock::MemoryStats(blocks, total, histogram); } + virtual size_t GetEstimatedAllocatedSize(size_t size) { + return size; + } + virtual size_t GetAllocatedSize(void* p) { if (p) { + RAW_CHECK(GetOwnership(p) != MallocExtension::kNotOwned, + "ptr not allocated by tcmalloc"); return MallocBlock::FromRawPointer(p)->data_size(); } return 0; } - virtual size_t GetEstimatedAllocatedSize(size_t size) { - return size; + + virtual MallocExtension::Ownership GetOwnership(const void* p) { + if (p) { + const MallocBlock* mb = MallocBlock::FromRawPointer(p); + return TCMallocImplementation::GetOwnership(mb); + } + return MallocExtension::kNotOwned; // nobody owns NULL } virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) { @@ -1038,8 +1049,10 @@ REGISTER_MODULE_INITIALIZER(debugallocation, { // ========================================================================= // // This is mostly the same a cpp_alloc in tcmalloc.cc. -// TODO(csilvers): write a wrapper for new-handler so we don't have to -// copy this code so much. +// TODO(csilvers): change Allocate() above to call cpp_alloc, so we +// don't have to reproduce the logic here. To make tc_new_mode work +// properly, I think we'll need to separate out the logic of throwing +// from the logic of calling the new-handler. inline void* debug_cpp_alloc(size_t size, int new_type, bool nothrow) { for (;;) { void* p = DebugAllocate(size, new_type); @@ -1355,29 +1368,5 @@ extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW { #endif extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW { - if (!ptr) { - return 0; - } - MallocBlock* mb = MallocBlock::FromRawPointer(ptr); - // This is just to make sure we actually own mb (and ptr). We don't - // use the actual value, just the 'exception' it raises on error. - (void)BASE_MALLOC_SIZE(mb); - return mb->data_size(); -} - -// Override __libc_memalign in libc on linux boxes. -// They have a bug in libc that causes them (very rarely) to allocate -// with __libc_memalign() yet deallocate with free(). -// This function is an exception to the rule of calling MallocHook method -// from the stack frame of the allocation function; -// heap-checker handles this special case explicitly. -static void *MemalignOverride(size_t align, size_t size, const void *caller) - __THROW ATTRIBUTE_SECTION(google_malloc); - -static void *MemalignOverride(size_t align, size_t size, const void *caller) - __THROW { - void *p = do_debug_memalign_or_debug_cpp_memalign(align, size); - MallocHook::InvokeNewHook(p, size); - return p; + return MallocExtension::instance()->GetAllocatedSize(ptr); } -void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride; diff --git a/third_party/tcmalloc/vendor/src/google/heap-checker.h b/third_party/tcmalloc/vendor/src/google/heap-checker.h index f46f353..a431fe9 100644 --- a/third_party/tcmalloc/vendor/src/google/heap-checker.h +++ b/third_party/tcmalloc/vendor/src/google/heap-checker.h @@ -185,8 +185,7 @@ class PERFTOOLS_DLL_DECL HeapLeakChecker { // for the purposes of heap leak checking. // If 'ptr' does not point to an active allocated object // at the time of this call, it is ignored; - // but if it does, the object must not get deleted from the heap later on; - // it must also be not already ignored at the time of this call. + // but if it does, the object must not get deleted from the heap later on. // // See also HiddenPointer, below, if you need to prevent a pointer from // being traversed by the heap checker but do not wish to transitively diff --git a/third_party/tcmalloc/vendor/src/google/malloc_extension.h b/third_party/tcmalloc/vendor/src/google/malloc_extension.h index 0e15c04..4b06b2d 100644 --- a/third_party/tcmalloc/vendor/src/google/malloc_extension.h +++ b/third_party/tcmalloc/vendor/src/google/malloc_extension.h @@ -81,9 +81,6 @@ class SysAllocator { // Returns NULL if failed. Otherwise, the returned pointer p up to and // including (p + actual_size -1) have been allocated. virtual void* Alloc(size_t size, size_t *actual_size, size_t alignment) = 0; - - // Notification that command-line flags have been initialized. - virtual void FlagsInitialized() = 0; }; // The default implementations of the following routines do nothing. @@ -103,6 +100,7 @@ class PERFTOOLS_DLL_DECL MallocExtension { // See "verify_memory.h" to see what these routines do virtual bool VerifyAllMemory(); + // TODO(csilvers): change these to const void*. virtual bool VerifyNewMemory(void* p); virtual bool VerifyArrayNewMemory(void* p); virtual bool VerifyMallocMemory(void* p); @@ -283,8 +281,27 @@ class PERFTOOLS_DLL_DECL MallocExtension { // will return 0.) // This is equivalent to malloc_size() in OS X, malloc_usable_size() // in glibc, and _msize() for windows. + // TODO(csilvers): change to const void*. virtual size_t GetAllocatedSize(void* p); + // Returns kOwned if this malloc implementation allocated the memory + // pointed to by p, or kNotOwned if some other malloc implementation + // allocated it or p is NULL. May also return kUnknownOwnership if + // the malloc implementation does not keep track of ownership. + // REQUIRES: p must be a value returned from a previous call to + // malloc(), calloc(), realloc(), memalign(), posix_memalign(), + // valloc(), pvalloc(), new, or new[], and must refer to memory that + // is currently allocated (so, for instance, you should not pass in + // a pointer after having called free() on it). + enum Ownership { + // NOTE: Enum values MUST be kept in sync with the version in + // malloc_extension_c.h + kUnknownOwnership = 0, + kOwned, + kNotOwned + }; + virtual Ownership GetOwnership(const void* p); + // The current malloc implementation. Always non-NULL. static MallocExtension* instance(); diff --git a/third_party/tcmalloc/vendor/src/google/malloc_extension_c.h b/third_party/tcmalloc/vendor/src/google/malloc_extension_c.h index fcaa8cd..e3f7f79 100644 --- a/third_party/tcmalloc/vendor/src/google/malloc_extension_c.h +++ b/third_party/tcmalloc/vendor/src/google/malloc_extension_c.h @@ -80,6 +80,18 @@ PERFTOOLS_DLL_DECL void MallocExtension_ReleaseFreeMemory(void); PERFTOOLS_DLL_DECL size_t MallocExtension_GetEstimatedAllocatedSize(size_t size); PERFTOOLS_DLL_DECL size_t MallocExtension_GetAllocatedSize(void* p); +/* + * NOTE: These enum values MUST be kept in sync with the version in + * malloc_extension.h + */ +typedef enum { + MallocExtension_kUnknownOwnership = 0, + MallocExtension_kOwned, + MallocExtension_kNotOwned +} MallocExtension_Ownership; + +PERFTOOLS_DLL_DECL MallocExtension_Ownership MallocExtension_GetOwnership(const void* p); + #ifdef __cplusplus } // extern "C" #endif diff --git a/third_party/tcmalloc/vendor/src/google/malloc_hook.h b/third_party/tcmalloc/vendor/src/google/malloc_hook.h index 3e2ef45..245d0e1 100644 --- a/third_party/tcmalloc/vendor/src/google/malloc_hook.h +++ b/third_party/tcmalloc/vendor/src/google/malloc_hook.h @@ -81,6 +81,14 @@ extern "C" { # endif #endif +// The C++ methods below call the C version (MallocHook_*), and thus +// convert between an int and a bool. Windows complains about this +// (a "performance warning") which we don't care about, so we suppress. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4800) +#endif + // Note: malloc_hook_c.h defines MallocHook_*Hook and // MallocHook_{Add,Remove}*Hook. The version of these inside the MallocHook // class are defined in terms of the malloc_hook_c version. See malloc_hook_c.h @@ -342,4 +350,9 @@ class PERFTOOLS_DLL_DECL MallocHook { static void InvokeSbrkHookSlow(const void* result, ptrdiff_t increment); }; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + #endif /* _MALLOC_HOOK_H_ */ diff --git a/third_party/tcmalloc/vendor/src/heap-checker.cc b/third_party/tcmalloc/vendor/src/heap-checker.cc index 6fb2a62..8473739 100644 --- a/third_party/tcmalloc/vendor/src/heap-checker.cc +++ b/third_party/tcmalloc/vendor/src/heap-checker.cc @@ -52,7 +52,7 @@ #include <time.h> #include <assert.h> -#ifdef HAVE_LINUX_PTRACE_H +#if defined(HAVE_LINUX_PTRACE_H) && !defined(__native_client__) #include <linux/ptrace.h> #endif #ifdef HAVE_SYS_SYSCALL_H @@ -278,10 +278,6 @@ static bool constructor_heap_profiling = false; static const int heap_checker_info_level = 0; //---------------------------------------------------------------------- -// Cancel our InitialMallocHook_* if present. -static void CancelInitialMallocHooks(); // defined below - -//---------------------------------------------------------------------- // HeapLeakChecker's own memory allocator that is // independent of the normal program allocator. //---------------------------------------------------------------------- @@ -1473,7 +1469,7 @@ void HeapLeakChecker::IgnoreObject(const void* ptr) { IgnoredObjectsMap; } if (!ignored_objects->insert(make_pair(AsInt(ptr), object_size)).second) { - RAW_LOG(FATAL, "Object at %p is already being ignored", ptr); + RAW_LOG(WARNING, "Object at %p is already being ignored", ptr); } } } diff --git a/third_party/tcmalloc/vendor/src/libc_override.h b/third_party/tcmalloc/vendor/src/libc_override.h new file mode 100644 index 0000000..c198e6a --- /dev/null +++ b/third_party/tcmalloc/vendor/src/libc_override.h @@ -0,0 +1,90 @@ +// Copyright (c) 2011, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Craig Silverstein <opensource@google.com> +// +// This .h file imports the code that causes tcmalloc to override libc +// versions of malloc/free/new/delete/etc. That is, it provides the +// logic that makes it so calls to malloc(10) go through tcmalloc, +// rather than the default (libc) malloc. +// +// This file also provides a method: ReplaceSystemAlloc(), that every +// libc_override_*.h file it #includes is required to provide. This +// is called when first setting up tcmalloc -- that is, when a global +// constructor in tcmalloc.cc is executed -- to do any initialization +// work that may be required for this OS. (Note we cannot entirely +// control when tcmalloc is initialized, and the system may do some +// mallocs and frees before this routine is called.) It may be a +// noop. +// +// Every libc has its own way of doing this, and sometimes the compiler +// matters too, so we have a different file for each libc, and often +// for different compilers and OS's. + +#ifndef TCMALLOC_LIBC_OVERRIDE_INL_H_ +#define TCMALLOC_LIBC_OVERRIDE_INL_H_ + +#include <config.h> +#ifdef HAVE_FEATURES_H +#include <features.h> // for __GLIBC__ +#endif +#include <google/tcmalloc.h> + +static void ReplaceSystemAlloc(); // defined in the .h files below + +// For windows, there are two ways to get tcmalloc. If we're +// patching, then src/windows/patch_function.cc will do the necessary +// overriding here. Otherwise, we doing the 'redefine' trick, where +// we remove malloc/new/etc from mscvcrt.dll, and just need to define +// them now. +#if defined(_WIN32) && defined(WIN32_DO_PATCHING) +void PatchWindowsFunctions(); // in src/windows/patch_function.cc +static void ReplaceSystemAlloc() { PatchWindowsFunctions(); } + +#elif defined(_WIN32) && !defined(WIN32_DO_PATCHING) +#include "libc_override_redefine.h" + +#elif defined(__APPLE__) +#include "libc_override_osx.h" + +#elif defined(__GLIBC__) +#include "libc_override_glibc.h" + +// Not all gcc systems necessarily support weak symbols, but all the +// ones I know of do, so for now just assume they all do. +#elif defined(__GNUC__) +#include "libc_override_gcc_and_weak.h" + +#else +#error Need to add support for your libc/OS here + +#endif + +#endif // TCMALLOC_LIBC_OVERRIDE_INL_H_ diff --git a/third_party/tcmalloc/vendor/src/libc_override_gcc_and_weak.h b/third_party/tcmalloc/vendor/src/libc_override_gcc_and_weak.h new file mode 100644 index 0000000..3d801d1 --- /dev/null +++ b/third_party/tcmalloc/vendor/src/libc_override_gcc_and_weak.h @@ -0,0 +1,99 @@ +// Copyright (c) 2011, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Craig Silverstein <opensource@google.com> +// +// Used to override malloc routines on systems that define the +// memory allocation routines to be weak symbols in their libc +// (almost all unix-based systems are like this), on gcc, which +// suppports the 'alias' attribute. + +#ifndef TCMALLOC_LIBC_OVERRIDE_GCC_AND_WEAK_INL_H_ +#define TCMALLOC_LIBC_OVERRIDE_GCC_AND_WEAK_INL_H_ + +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> // for __THROW +#endif +#include <google/tcmalloc.h> + +#ifndef __THROW // I guess we're not on a glibc-like system +# define __THROW // __THROW is just an optimization, so ok to make it "" +#endif + +#ifndef __GNUC__ +# error libc_override_gcc_and_weak.h is for gcc distributions only. +#endif + +#define ALIAS(tc_fn) __attribute__ ((alias (#tc_fn))) + +void* operator new(size_t size) throw (std::bad_alloc) + ALIAS(tc_new); +void operator delete(void* p) __THROW + ALIAS(tc_delete); +void* operator new[](size_t size) throw (std::bad_alloc) + ALIAS(tc_newarray); +void operator delete[](void* p) __THROW + ALIAS(tc_deletearray); +void* operator new(size_t size, const std::nothrow_t& nt) __THROW + ALIAS(tc_new_nothrow); +void* operator new[](size_t size, const std::nothrow_t& nt) __THROW + ALIAS(tc_newarray_nothrow); +void operator delete(void* p, const std::nothrow_t& nt) __THROW + ALIAS(tc_delete_nothrow); +void operator delete[](void* p, const std::nothrow_t& nt) __THROW + ALIAS(tc_deletearray_nothrow); + +extern "C" { + void* malloc(size_t size) __THROW ALIAS(tc_malloc); + void free(void* ptr) __THROW ALIAS(tc_free); + void* realloc(void* ptr, size_t size) __THROW ALIAS(tc_realloc); + void* calloc(size_t n, size_t size) __THROW ALIAS(tc_calloc); + void cfree(void* ptr) __THROW ALIAS(tc_cfree); + void* memalign(size_t align, size_t s) __THROW ALIAS(tc_memalign); + void* valloc(size_t size) __THROW ALIAS(tc_valloc); + void* pvalloc(size_t size) __THROW ALIAS(tc_pvalloc); + int posix_memalign(void** r, size_t a, size_t s) __THROW + ALIAS(tc_posix_memalign); + void malloc_stats(void) __THROW ALIAS(tc_malloc_stats); + int mallopt(int cmd, int value) __THROW ALIAS(tc_mallopt); +#ifdef HAVE_STRUCT_MALLINFO + struct mallinfo mallinfo(void) __THROW ALIAS(tc_mallinfo); +#endif + size_t malloc_size(void* p) __THROW ALIAS(tc_malloc_size); + size_t malloc_usable_size(void* p) __THROW ALIAS(tc_malloc_size); +} // extern "C" + +#undef ALIAS + +// No need to do anything at tcmalloc-registration time: we do it all +// via overriding weak symbols (at link time). +static void ReplaceSystemAlloc() { } + +#endif // TCMALLOC_LIBC_OVERRIDE_GCC_AND_WEAK_INL_H_ diff --git a/third_party/tcmalloc/vendor/src/libc_override_glibc.h b/third_party/tcmalloc/vendor/src/libc_override_glibc.h new file mode 100644 index 0000000..4490a7a --- /dev/null +++ b/third_party/tcmalloc/vendor/src/libc_override_glibc.h @@ -0,0 +1,148 @@ +// Copyright (c) 2011, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Craig Silverstein <opensource@google.com> +// +// Used to override malloc routines on systems that are using glibc. + +#ifndef TCMALLOC_LIBC_OVERRIDE_GLIBC_INL_H_ +#define TCMALLOC_LIBC_OVERRIDE_GLIBC_INL_H_ + +#include <config.h> +#include <features.h> // for __GLIBC__ +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> // for __THROW +#endif +#include <google/tcmalloc.h> + +#ifndef __GLIBC__ +# error libc_override_glibc.h is for glibc distributions only. +#endif + +// In glibc, the memory-allocation methods are weak symbols, so we can +// just override them with our own. If we're using gcc, we can use +// __attribute__((alias)) to do the overriding easily (exception: +// Mach-O, which doesn't support aliases). Otherwise we have to use a +// function call. +#if !defined(__GNUC__) || defined(__MACH__) + +// This also defines ReplaceSystemAlloc(). +# include "libc_override_redefine.h" // defines functions malloc()/etc + +#else // #if !defined(__GNUC__) || defined(__MACH__) + +// If we get here, we're a gcc system, so do all the overriding we do +// with gcc. This does the overriding of all the 'normal' memory +// allocation. This also defines ReplaceSystemAlloc(). +# include "libc_override_gcc_and_weak.h" + +// We also have to do some glibc-specific overriding. Some library +// routines on RedHat 9 allocate memory using malloc() and free it +// using __libc_free() (or vice-versa). Since we provide our own +// implementations of malloc/free, we need to make sure that the +// __libc_XXX variants (defined as part of glibc) also point to the +// same implementations. Since it only matters for redhat, we +// do it inside the gcc #ifdef, since redhat uses gcc. +// TODO(csilvers): only do this if we detect we're an old enough glibc? + +#define ALIAS(tc_fn) __attribute__ ((alias (#tc_fn))) +extern "C" { + void* __libc_malloc(size_t size) ALIAS(tc_malloc); + void __libc_free(void* ptr) ALIAS(tc_free); + void* __libc_realloc(void* ptr, size_t size) ALIAS(tc_realloc); + void* __libc_calloc(size_t n, size_t size) ALIAS(tc_calloc); + void __libc_cfree(void* ptr) ALIAS(tc_cfree); + void* __libc_memalign(size_t align, size_t s) ALIAS(tc_memalign); + void* __libc_valloc(size_t size) ALIAS(tc_valloc); + void* __libc_pvalloc(size_t size) ALIAS(tc_pvalloc); + int __posix_memalign(void** r, size_t a, size_t s) ALIAS(tc_posix_memalign); +} // extern "C" +#undef ALIAS + +#endif // #if defined(__GNUC__) && !defined(__MACH__) + + +// We also have to hook libc malloc. While our work with weak symbols +// should make sure libc malloc is never called in most situations, it +// can be worked around by shared libraries with the DEEPBIND +// environment variable set. The below hooks libc to call our malloc +// routines even in that situation. In other situations, this hook +// should never be called. +extern "C" { +static void* glibc_override_malloc(size_t size, const void *caller) { + return tc_malloc(size); +} +static void* glibc_override_realloc(void *ptr, size_t size, + const void *caller) { + return tc_realloc(ptr, size); +} +static void glibc_override_free(void *ptr, const void *caller) { + tc_free(ptr); +} +static void* glibc_override_memalign(size_t align, size_t size, + const void *caller) { + return tc_memalign(align, size); +} + +// We should be using __malloc_initialize_hook here, like the #if 0 +// code below. (See http://swoolley.org/man.cgi/3/malloc_hook.) +// However, this causes weird linker errors with programs that link +// with -static, so instead we just assign the vars directly at +// static-constructor time. That should serve the same effect of +// making sure the hooks are set before the first malloc call the +// program makes. +#if 0 +#include <malloc.h> // for __malloc_hook, etc. +void glibc_override_malloc_init_hook(void) { + __malloc_hook = glibc_override_malloc; + __realloc_hook = glibc_override_realloc; + __free_hook = glibc_override_free; + __memalign_hook = glibc_override_memalign; +} + +void (* MALLOC_HOOK_MAYBE_VOLATILE __malloc_initialize_hook)(void) + = &glibc_override_malloc_init_hook; +#endif + +void* (* MALLOC_HOOK_MAYBE_VOLATILE __malloc_hook)(size_t, const void*) + = &glibc_override_malloc; +void* (* MALLOC_HOOK_MAYBE_VOLATILE __realloc_hook)(void*, size_t, const void*) + = &glibc_override_realloc; +void (* MALLOC_HOOK_MAYBE_VOLATILE __free_hook)(void*, const void*) + = &glibc_override_free; +void* (* MALLOC_HOOK_MAYBE_VOLATILE __memalign_hook)(size_t,size_t, const void*) + = &glibc_override_memalign; + +} // extern "C" + +// No need to write ReplaceSystemAlloc(); one of the #includes above +// did it for us. + +#endif // TCMALLOC_LIBC_OVERRIDE_GLIBC_INL_H_ diff --git a/third_party/tcmalloc/vendor/src/libc_override_osx.h b/third_party/tcmalloc/vendor/src/libc_override_osx.h new file mode 100644 index 0000000..0ccf9a3 --- /dev/null +++ b/third_party/tcmalloc/vendor/src/libc_override_osx.h @@ -0,0 +1,257 @@ +// Copyright (c) 2011, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Craig Silverstein <opensource@google.com> +// +// Used to override malloc routines on OS X systems. We use the +// malloc-zone functionality built into OS X to register our malloc +// routine. +// +// 1) We used to use the normal 'override weak libc malloc/etc' +// technique for OS X. This is not optimal because mach does not +// support the 'alias' attribute, so we had to have forwarding +// functions. It also does not work very well with OS X shared +// libraries (dylibs) -- in general, the shared libs don't use +// tcmalloc unless run with the DYLD_FORCE_FLAT_NAMESPACE envvar. +// +// 2) Another approach would be to use an interposition array: +// static const interpose_t interposers[] __attribute__((section("__DATA, __interpose"))) = { +// { (void *)tc_malloc, (void *)malloc }, +// { (void *)tc_free, (void *)free }, +// }; +// This requires the user to set the DYLD_INSERT_LIBRARIES envvar, so +// is not much better. +// +// 3) Registering a new malloc zone avoids all these issues: +// http://www.opensource.apple.com/source/Libc/Libc-583/include/malloc/malloc.h +// http://www.opensource.apple.com/source/Libc/Libc-583/gen/malloc.c +// If we make tcmalloc the default malloc zone (undocumented but +// possible) then all new allocs use it, even those in shared +// libraries. Allocs done before tcmalloc was installed, or in libs +// that aren't using tcmalloc for some reason, will correctly go +// through the malloc-zone interface when free-ing, and will pick up +// the libc free rather than tcmalloc free. So it should "never" +// cause a crash (famous last words). +// +// 4) The routines one must define for one's own malloc have changed +// between OS X versions. This requires some hoops on our part, but +// is only really annoying when it comes to posix_memalign. The right +// behavior there depends on what OS version tcmalloc was compiled on, +// but also what OS version the program is running on. For now, we +// punt and don't implement our own posix_memalign. Apps that really +// care can use tc_posix_memalign directly. + +#ifndef TCMALLOC_LIBC_OVERRIDE_OSX_INL_H_ +#define TCMALLOC_LIBC_OVERRIDE_OSX_INL_H_ + +#include <config.h> +#ifdef HAVE_FEATURES_H +#include <features.h> +#endif +#include <google/tcmalloc.h> + +#if !defined(__APPLE__) +# error libc_override_glibc-osx.h is for OS X distributions only. +#endif + +#include <AvailabilityMacros.h> +#include <malloc/malloc.h> + +// We need to provide wrappers around all the libc functions. +namespace { +size_t mz_size(malloc_zone_t* zone, const void* ptr) { + if (MallocExtension::instance()->GetOwnership(ptr) != MallocExtension::kOwned) + return 0; // malloc_zone semantics: return 0 if we don't own the memory + + // TODO(csilvers): change this method to take a const void*, one day. + return MallocExtension::instance()->GetAllocatedSize(const_cast<void*>(ptr)); +} + +void* mz_malloc(malloc_zone_t* zone, size_t size) { + return tc_malloc(size); +} + +void* mz_calloc(malloc_zone_t* zone, size_t num_items, size_t size) { + return tc_calloc(num_items, size); +} + +void* mz_valloc(malloc_zone_t* zone, size_t size) { + return tc_valloc(size); +} + +void mz_free(malloc_zone_t* zone, void* ptr) { + return tc_free(ptr); +} + +void* mz_realloc(malloc_zone_t* zone, void* ptr, size_t size) { + return tc_realloc(ptr, size); +} + +void* mz_memalign(malloc_zone_t* zone, size_t align, size_t size) { + return tc_memalign(align, size); +} + +void mz_destroy(malloc_zone_t* zone) { + // A no-op -- we will not be destroyed! +} + +// malloc_introspection callbacks. I'm not clear on what all of these do. +kern_return_t mi_enumerator(task_t task, void *, + unsigned type_mask, vm_address_t zone_address, + memory_reader_t reader, + vm_range_recorder_t recorder) { + // Should enumerate all the pointers we have. Seems like a lot of work. + return KERN_FAILURE; +} + +size_t mi_good_size(malloc_zone_t *zone, size_t size) { + // I think it's always safe to return size, but we maybe could do better. + return size; +} + +boolean_t mi_check(malloc_zone_t *zone) { + return MallocExtension::instance()->VerifyAllMemory(); +} + +void mi_print(malloc_zone_t *zone, boolean_t verbose) { + int bufsize = 8192; + if (verbose) + bufsize = 102400; // I picked this size arbitrarily + char* buffer = new char[bufsize]; + MallocExtension::instance()->GetStats(buffer, bufsize); + fprintf(stdout, "%s", buffer); + delete[] buffer; +} + +void mi_log(malloc_zone_t *zone, void *address) { + // I don't think we support anything like this +} + +void mi_force_lock(malloc_zone_t *zone) { + // Hopefully unneeded by us! +} + +void mi_force_unlock(malloc_zone_t *zone) { + // Hopefully unneeded by us! +} + +void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { + // TODO(csilvers): figure out how to fill these out + stats->blocks_in_use = 0; + stats->size_in_use = 0; + stats->max_size_in_use = 0; + stats->size_allocated = 0; +} + +boolean_t mi_zone_locked(malloc_zone_t *zone) { + return false; // Hopefully unneeded by us! +} + +} // unnamed namespace + +// OS X doesn't have pvalloc, cfree, malloc_statc, etc, so we can just +// define our own. :-) OS X supplies posix_memalign in some versions +// but not others, either strongly or weakly linked, in a way that's +// difficult enough to code to correctly, that I just don't try to +// support either memalign() or posix_memalign(). If you need them +// and are willing to code to tcmalloc, you can use tc_posix_memalign(). +extern "C" { + void cfree(void* p) { tc_cfree(p); } + void* pvalloc(size_t s) { return tc_pvalloc(s); } + void malloc_stats(void) { tc_malloc_stats(); } + int mallopt(int cmd, int v) { return tc_mallopt(cmd, v); } + // No struct mallinfo on OS X, so don't define mallinfo(). + // An alias for malloc_size(), which OS X defines. + size_t malloc_usable_size(void* p) { return tc_malloc_size(p); } +} // extern "C" + +static void ReplaceSystemAlloc() { + static malloc_introspection_t tcmalloc_introspection; + memset(&tcmalloc_introspection, 0, sizeof(tcmalloc_introspection)); + + tcmalloc_introspection.enumerator = &mi_enumerator; + tcmalloc_introspection.good_size = &mi_good_size; + tcmalloc_introspection.check = &mi_check; + tcmalloc_introspection.print = &mi_print; + tcmalloc_introspection.log = &mi_log; + tcmalloc_introspection.force_lock = &mi_force_lock; + tcmalloc_introspection.force_unlock = &mi_force_unlock; + + static malloc_zone_t tcmalloc_zone; + memset(&tcmalloc_zone, 0, sizeof(malloc_zone_t)); + + // Start with a version 4 zone which is used for OS X 10.4 and 10.5. + tcmalloc_zone.version = 4; + tcmalloc_zone.zone_name = "tcmalloc"; + tcmalloc_zone.size = &mz_size; + tcmalloc_zone.malloc = &mz_malloc; + tcmalloc_zone.calloc = &mz_calloc; + tcmalloc_zone.valloc = &mz_valloc; + tcmalloc_zone.free = &mz_free; + tcmalloc_zone.realloc = &mz_realloc; + tcmalloc_zone.destroy = &mz_destroy; + tcmalloc_zone.batch_malloc = NULL; + tcmalloc_zone.batch_free = NULL; + tcmalloc_zone.introspect = &tcmalloc_introspection; + + // from AvailabilityMacros.h +#if defined(MAC_OS_X_VERSION_10_6) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + // Switch to version 6 on OSX 10.6 to support memalign. + tcmalloc_zone.version = 6; + tcmalloc_zone.free_definite_size = NULL; + tcmalloc_zone.memalign = &mz_memalign; + tcmalloc_introspection.zone_locked = &mi_zone_locked; + + // Request the default purgable zone to force its creation. The + // current default zone is registered with the purgable zone for + // doing tiny and small allocs. Sadly, it assumes that the default + // zone is the szone implementation from OS X and will crash if it + // isn't. By creating the zone now, this will be true and changing + // the default zone won't cause a problem. (OS X 10.6 and higher.) + malloc_default_purgeable_zone(); +#endif + + // Register the tcmalloc zone. At this point, it will not be the + // default zone. + malloc_zone_register(&tcmalloc_zone); + + // Unregister and reregister the default zone. Unregistering swaps + // the specified zone with the last one registered which for the + // default zone makes the more recently registered zone the default + // zone. The default zone is then re-registered to ensure that + // allocations made from it earlier will be handled correctly. + // Things are not guaranteed to work that way, but it's how they work now. + malloc_zone_t *default_zone = malloc_default_zone(); + malloc_zone_unregister(default_zone); + malloc_zone_register(default_zone); +} + +#endif // TCMALLOC_LIBC_OVERRIDE_OSX_INL_H_ diff --git a/third_party/tcmalloc/vendor/src/libc_override_redefine.h b/third_party/tcmalloc/vendor/src/libc_override_redefine.h new file mode 100644 index 0000000..d8d999c --- /dev/null +++ b/third_party/tcmalloc/vendor/src/libc_override_redefine.h @@ -0,0 +1,93 @@ +// Copyright (c) 2011, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Craig Silverstein <opensource@google.com> +// +// Used on systems that don't have their own definition of +// malloc/new/etc. (Typically this will be a windows msvcrt.dll that +// has been edited to remove the definitions.) We can just define our +// own as normal functions. +// +// This should also work on systems were all the malloc routines are +// defined as weak symbols, and there's no support for aliasing. + +#ifndef TCMALLOC_LIBC_OVERRIDE_REDEFINE_H_ +#define TCMALLOC_LIBC_OVERRIDE_REDEFINE_H_ + +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> // for __THROW +#endif + +#ifndef __THROW // I guess we're not on a glibc-like system +# define __THROW // __THROW is just an optimization, so ok to make it "" +#endif + +void* operator new(size_t size) { return tc_new(size); } +void operator delete(void* p) __THROW { tc_delete(p); } +void* operator new[](size_t size) { return tc_newarray(size); } +void operator delete[](void* p) __THROW { tc_deletearray(p); } +void* operator new(size_t size, const std::nothrow_t& nt) __THROW { + return tc_new_nothrow(size, nt); +} +void* operator new[](size_t size, const std::nothrow_t& nt) __THROW { + return tc_newarray_nothrow(size, nt); +} +void operator delete(void* ptr, const std::nothrow_t& nt) __THROW { + return tc_delete_nothrow(ptr, nt); +} +void operator delete[](void* ptr, const std::nothrow_t& nt) __THROW { + return tc_deletearray_nothrow(ptr, nt); +} +extern "C" { + void* malloc(size_t s) __THROW { return tc_malloc(s); } + void free(void* p) __THROW { tc_free(p); } + void* realloc(void* p, size_t s) __THROW { return tc_realloc(p, s); } + void* calloc(size_t n, size_t s) __THROW { return tc_calloc(n, s); } + void cfree(void* p) __THROW { tc_cfree(p); } + void* memalign(size_t a, size_t s) __THROW { return tc_memalign(a, s); } + void* valloc(size_t s) __THROW { return tc_valloc(s); } + void* pvalloc(size_t s) __THROW { return tc_pvalloc(s); } + int posix_memalign(void** r, size_t a, size_t s) __THROW { + return tc_posix_memalign(r, a, s); + } + void malloc_stats(void) __THROW { tc_malloc_stats(); } + int mallopt(int cmd, int v) __THROW { return tc_mallopt(cmd, v); } +#ifdef HAVE_STRUCT_MALLINFO + struct mallinfo mallinfo(void) __THROW { return tc_mallinfo(); } +#endif + size_t malloc_size(void* p) __THROW { return tc_malloc_size(p); } + size_t malloc_usable_size(void* p) __THROW { return tc_malloc_size(p); } +} // extern "C" + +// No need to do anything at tcmalloc-registration time: we do it all +// via overriding weak symbols (at link time). +static void ReplaceSystemAlloc() { } + +#endif // TCMALLOC_LIBC_OVERRIDE_REDEFINE_H_ diff --git a/third_party/tcmalloc/vendor/src/malloc_extension.cc b/third_party/tcmalloc/vendor/src/malloc_extension.cc index e9a0da7..bf946e6 100644 --- a/third_party/tcmalloc/vendor/src/malloc_extension.cc +++ b/third_party/tcmalloc/vendor/src/malloc_extension.cc @@ -48,6 +48,7 @@ #include "google/heap-checker.h" #endif #include "google/malloc_extension.h" +#include "google/malloc_extension_c.h" #include "maybe_threads.h" using STL_NAMESPACE::string; @@ -177,9 +178,14 @@ size_t MallocExtension::GetEstimatedAllocatedSize(size_t size) { } size_t MallocExtension::GetAllocatedSize(void* p) { + assert(GetOwnership(p) != kNotOwned); return 0; } +MallocExtension::Ownership MallocExtension::GetOwnership(const void* p) { + return kUnknownOwnership; +} + void MallocExtension::GetFreeListSizes( vector<MallocExtension::FreeListInfo>* v) { v->clear(); @@ -238,11 +244,11 @@ void PrintCountAndSize(MallocExtensionWriter* writer, uintptr_t count, uintptr_t size) { char buf[100]; snprintf(buf, sizeof(buf), - "%6lld: %8lld [%6lld: %8lld] @", - static_cast<long long>(count), - static_cast<long long>(size), - static_cast<long long>(count), - static_cast<long long>(size)); + "%6"PRIu64": %8"PRIu64" [%6"PRIu64": %8"PRIu64"] @", + static_cast<uint64>(count), + static_cast<uint64>(size), + static_cast<uint64>(count), + static_cast<uint64>(size)); writer->append(buf, strlen(buf)); } @@ -357,3 +363,10 @@ C_SHIM(ReleaseFreeMemory, void, (void), ()); C_SHIM(ReleaseToSystem, void, (size_t num_bytes), (num_bytes)); C_SHIM(GetEstimatedAllocatedSize, size_t, (size_t size), (size)); C_SHIM(GetAllocatedSize, size_t, (void* p), (p)); + +// Can't use the shim here because of the need to translate the enums. +extern "C" +MallocExtension_Ownership MallocExtension_GetOwnership(const void* p) { + return static_cast<MallocExtension_Ownership>( + MallocExtension::instance()->GetOwnership(p)); +} diff --git a/third_party/tcmalloc/vendor/src/malloc_hook-inl.h b/third_party/tcmalloc/vendor/src/malloc_hook-inl.h index b24b1c6..6210784 100644 --- a/third_party/tcmalloc/vendor/src/malloc_hook-inl.h +++ b/third_party/tcmalloc/vendor/src/malloc_hook-inl.h @@ -104,7 +104,7 @@ static const int kHookListMaxValues = 7; // HookList: a class that provides synchronized insertions and removals and // lockless traversal. Most of the implementation is in malloc_hook.cc. template <typename T> -struct HookList { +struct PERFTOOLS_DLL_DECL HookList { COMPILE_ASSERT(sizeof(T) <= sizeof(AtomicWord), T_should_fit_in_AtomicWord); // Adds value to the list. Note that duplicates are allowed. Thread-safe and diff --git a/third_party/tcmalloc/vendor/src/malloc_hook.cc b/third_party/tcmalloc/vendor/src/malloc_hook.cc index 5a61362..dc4539c 100644 --- a/third_party/tcmalloc/vendor/src/malloc_hook.cc +++ b/third_party/tcmalloc/vendor/src/malloc_hook.cc @@ -283,7 +283,7 @@ int HookList<T>::Traverse(T* output_array, int n) const { // Explicit instantiation for malloc_hook_test.cc. This ensures all the methods // are instantiated. -template class HookList<MallocHook::NewHook>; +template struct HookList<MallocHook::NewHook>; HookList<MallocHook::NewHook> new_hooks_ = INIT_HOOK_LIST_WITH_VALUE(&InitialNewHook); @@ -698,191 +698,19 @@ extern "C" int MallocHook_GetCallerStackTrace(void** result, int max_depth, #endif } -// On Linux/x86, we override mmap/munmap/mremap/sbrk -// and provide support for calling the related hooks. -// -// We define mmap() and mmap64(), which somewhat reimplements libc's mmap -// syscall stubs. Unfortunately libc only exports the stubs via weak symbols -// (which we're overriding with our mmap64() and mmap() wrappers) so we can't -// just call through to them. - - -#if defined(__linux) && \ - (defined(__i386__) || defined(__x86_64__) || defined(__PPC__)) -#include <unistd.h> -#include <syscall.h> -#include <sys/mman.h> -#include <errno.h> -#include "base/linux_syscall_support.h" - -// The x86-32 case and the x86-64 case differ: -// 32b has a mmap2() syscall, 64b does not. -// 64b and 32b have different calling conventions for mmap(). -#if defined(__x86_64__) || defined(__PPC64__) - -static inline void* do_mmap64(void *start, size_t length, - int prot, int flags, - int fd, __off64_t offset) __THROW { - return (void *)syscall(SYS_mmap, start, length, prot, flags, fd, offset); -} - -#elif defined(__i386__) || defined(__PPC__) - -static inline void* do_mmap64(void *start, size_t length, - int prot, int flags, - int fd, __off64_t offset) __THROW { - void *result; - - // Try mmap2() unless it's not supported - static bool have_mmap2 = true; - if (have_mmap2) { - static int pagesize = 0; - if (!pagesize) pagesize = getpagesize(); - - // Check that the offset is page aligned - if (offset & (pagesize - 1)) { - result = MAP_FAILED; - errno = EINVAL; - goto out; - } - - result = (void *)syscall(SYS_mmap2, - start, length, prot, flags, fd, - (off_t) (offset / pagesize)); - if (result != MAP_FAILED || errno != ENOSYS) goto out; - - // We don't have mmap2() after all - don't bother trying it in future - have_mmap2 = false; - } - - if (((off_t)offset) != offset) { - // If we're trying to map a 64-bit offset, fail now since we don't - // have 64-bit mmap() support. - result = MAP_FAILED; - errno = EINVAL; - goto out; - } - - { - // Fall back to old 32-bit offset mmap() call - // Old syscall interface cannot handle six args, so pass in an array - int32 args[6] = { (int32) start, length, prot, flags, fd, (off_t) offset }; - result = (void *)syscall(SYS_mmap, args); - } - out: - return result; -} - -# endif // defined(__x86_64__) - -// We use do_mmap64 abstraction to put MallocHook::InvokeMmapHook -// calls right into mmap and mmap64, so that the stack frames in the caller's -// stack are at the same offsets for all the calls of memory allocating -// functions. - -// Put all callers of MallocHook::Invoke* in this module into -// malloc_hook section, -// so that MallocHook::GetCallerStackTrace can function accurately: - -// Make sure mmap doesn't get #define'd away by <sys/mman.h> -#undef mmap - -extern "C" { - void* mmap64(void *start, size_t length, int prot, int flags, - int fd, __off64_t offset ) __THROW - ATTRIBUTE_SECTION(malloc_hook); - void* mmap(void *start, size_t length,int prot, int flags, - int fd, off_t offset) __THROW - ATTRIBUTE_SECTION(malloc_hook); - int munmap(void* start, size_t length) __THROW - ATTRIBUTE_SECTION(malloc_hook); - void* mremap(void* old_addr, size_t old_size, size_t new_size, - int flags, ...) __THROW - ATTRIBUTE_SECTION(malloc_hook); - void* sbrk(ptrdiff_t increment) __THROW - ATTRIBUTE_SECTION(malloc_hook); -} - -extern "C" void* mmap64(void *start, size_t length, int prot, int flags, - int fd, __off64_t offset) __THROW { - MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset); - void *result; - if (!MallocHook::InvokeMmapReplacement( - start, length, prot, flags, fd, offset, &result)) { - result = do_mmap64(start, length, prot, flags, fd, offset); - } - MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset); - return result; -} - -#if !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH) - -extern "C" void* mmap(void *start, size_t length, int prot, int flags, - int fd, off_t offset) __THROW { - MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset); - void *result; - if (!MallocHook::InvokeMmapReplacement( - start, length, prot, flags, fd, offset, &result)) { - result = do_mmap64(start, length, prot, flags, fd, - static_cast<size_t>(offset)); // avoid sign extension - } - MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset); - return result; -} - -#endif // !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH) +// On systems where we know how, we override mmap/munmap/mremap/sbrk +// to provide support for calling the related hooks (in addition, +// of course, to doing what these functions normally do). -extern "C" int munmap(void* start, size_t length) __THROW { - MallocHook::InvokeMunmapHook(start, length); - int result; - if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { - result = syscall(SYS_munmap, start, length); - } - return result; -} - -extern "C" void* mremap(void* old_addr, size_t old_size, size_t new_size, - int flags, ...) __THROW { - va_list ap; - va_start(ap, flags); - void *new_address = va_arg(ap, void *); - va_end(ap); - void* result = sys_mremap(old_addr, old_size, new_size, flags, new_address); - MallocHook::InvokeMremapHook(result, old_addr, old_size, new_size, flags, - new_address); - return result; -} - -// libc's version: -extern "C" void* __sbrk(ptrdiff_t increment); - -extern "C" void* sbrk(ptrdiff_t increment) __THROW { - MallocHook::InvokePreSbrkHook(increment); - void *result = __sbrk(increment); - MallocHook::InvokeSbrkHook(result, increment); - return result; -} - -/*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot, - int flags, int fd, off_t offset) { - void* result; - if (!MallocHook::InvokeMmapReplacement( - start, length, prot, flags, fd, offset, &result)) { - result = do_mmap64(start, length, prot, flags, fd, offset); - } - return result; -} +#if defined(__linux) +# include "malloc_hook_mmap_linux.h" -/*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) { - int result; - if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { - result = sys_munmap(start, length); - } - return result; -} +// This code doesn't even compile on my freebsd 8.1 (x86_64) system, +// so comment it out for now. TODO(csilvers): fix this! +#elif 0 && defined(__FreeBSD__) +# include "malloc_hook_mmap_freebsd.h" -#else // defined(__linux) && - // (defined(__i386__) || defined(__x86_64__) || defined(__PPC__)) +#else /*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { @@ -902,5 +730,4 @@ extern "C" void* sbrk(ptrdiff_t increment) __THROW { return result; } -#endif // defined(__linux) && - // (defined(__i386__) || defined(__x86_64__) || defined(__PPC__)) +#endif diff --git a/third_party/tcmalloc/vendor/src/malloc_hook_mmap_freebsd.h b/third_party/tcmalloc/vendor/src/malloc_hook_mmap_freebsd.h new file mode 100644 index 0000000..4ac2bb3 --- /dev/null +++ b/third_party/tcmalloc/vendor/src/malloc_hook_mmap_freebsd.h @@ -0,0 +1,111 @@ +// Copyright (c) 2011, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// Override mmap/munmap/mremap/sbrk to provide support for calling the +// related hooks (in addition, of course, to doing what these +// functions normally do). + +#ifndef __FreeBSD__ +# error Should only be including malloc_hook_mmap_freebsd.h on FreeBSD systems. +#endif + +#include <unistd.h> +#include <sys/syscall.h> +#include <sys/mman.h> +#include <errno.h> + +static inline void* do_mmap(void *start, size_t length, + int prot, int flags, + int fd, off_t offset) __THROW { + return (void *)syscall(SYS_mmap, start, length, prot, flags, fd, offset); +} + +// Make sure mmap doesn't get #define'd away by <sys/mman.h> +#undef mmap + +extern "C" { + void* mmap(void *start, size_t length,int prot, int flags, + int fd, off_t offset) __THROW + ATTRIBUTE_SECTION(malloc_hook); + int munmap(void* start, size_t length) __THROW + ATTRIBUTE_SECTION(malloc_hook); + void* sbrk(intptr_t increment) __THROW + ATTRIBUTE_SECTION(malloc_hook); +} + +static inline void* do_sbrk(intptr_t increment) { + void* curbrk; + + __asm__ __volatile__( + "movl .curbrk, %%eax;" + "movl %%eax, %0" + : "=r" (curbrk) + :: "%eax"); + + char* prevbrk = static_cast<char*>(curbrk); + void* newbrk = prevbrk + increment; + + if (brk(newbrk) == -1) { + assert(0); + return reinterpret_cast<void*>(static_cast<intptr_t>(-1)); + } + + return prevbrk; +} + + +extern "C" void* mmap(void *start, size_t length, int prot, int flags, + int fd, off_t offset) __THROW { + MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset); + void *result = do_mmap(start, length, prot, flags, fd, + static_cast<size_t>(offset)); // avoid sign extension + MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset); + return result; +} + +extern "C" int munmap(void* start, size_t length) __THROW { + MallocHook::InvokeMunmapHook(start, length); + return syscall(SYS_munmap, start, length); +} + +extern "C" void* sbrk(intptr_t increment) __THROW { + MallocHook::InvokePreSbrkHook(increment); + void *result = do_sbrk(increment); + MallocHook::InvokeSbrkHook(result, increment); + return result; +} + +/*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot, + int flags, int fd, off_t offset) { + return mmap(start, length, prot, flags, fd, offset); +} + +/*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) { + return munmap(start, length); +} diff --git a/third_party/tcmalloc/vendor/src/malloc_hook_mmap_linux.h b/third_party/tcmalloc/vendor/src/malloc_hook_mmap_linux.h new file mode 100644 index 0000000..0026589 --- /dev/null +++ b/third_party/tcmalloc/vendor/src/malloc_hook_mmap_linux.h @@ -0,0 +1,223 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Sanjay Ghemawat <opensource@google.com> + +// We define mmap() and mmap64(), which somewhat reimplements libc's mmap +// syscall stubs. Unfortunately libc only exports the stubs via weak symbols +// (which we're overriding with our mmap64() and mmap() wrappers) so we can't +// just call through to them. + +#ifndef __linux +# error Should only be including malloc_hook_mmap_linux.h on linux systems. +#endif + +#include <unistd.h> +#include <syscall.h> +#include <sys/mman.h> +#include <errno.h> +#include "base/linux_syscall_support.h" + +// The x86-32 case and the x86-64 case differ: +// 32b has a mmap2() syscall, 64b does not. +// 64b and 32b have different calling conventions for mmap(). +#if defined(__i386__) || defined(__PPC__) + +static inline void* do_mmap64(void *start, size_t length, + int prot, int flags, + int fd, __off64_t offset) __THROW { + void *result; + + // Try mmap2() unless it's not supported + static bool have_mmap2 = true; + if (have_mmap2) { + static int pagesize = 0; + if (!pagesize) pagesize = getpagesize(); + + // Check that the offset is page aligned + if (offset & (pagesize - 1)) { + result = MAP_FAILED; + errno = EINVAL; + goto out; + } + + result = (void *)syscall(SYS_mmap2, + start, length, prot, flags, fd, + (off_t) (offset / pagesize)); + if (result != MAP_FAILED || errno != ENOSYS) goto out; + + // We don't have mmap2() after all - don't bother trying it in future + have_mmap2 = false; + } + + if (((off_t)offset) != offset) { + // If we're trying to map a 64-bit offset, fail now since we don't + // have 64-bit mmap() support. + result = MAP_FAILED; + errno = EINVAL; + goto out; + } + + { + // Fall back to old 32-bit offset mmap() call + // Old syscall interface cannot handle six args, so pass in an array + int32 args[6] = { (int32) start, length, prot, flags, fd, (off_t) offset }; + result = (void *)syscall(SYS_mmap, args); + } + out: + return result; +} + +#define MALLOC_HOOK_HAVE_DO_MMAP64 1 + +#elif defined(__x86_64__) || defined(__PPC64__) // #if defined(__i386__) || ... + +static inline void* do_mmap64(void *start, size_t length, + int prot, int flags, + int fd, __off64_t offset) __THROW { + return (void *)syscall(SYS_mmap, start, length, prot, flags, fd, offset); +} + +#define MALLOC_HOOK_HAVE_DO_MMAP64 1 + +#endif // #if defined(__i386__) || defined(__PPC__) + + +#ifdef MALLOC_HOOK_HAVE_DO_MMAP64 + +// We use do_mmap64 abstraction to put MallocHook::InvokeMmapHook +// calls right into mmap and mmap64, so that the stack frames in the caller's +// stack are at the same offsets for all the calls of memory allocating +// functions. + +// Put all callers of MallocHook::Invoke* in this module into +// malloc_hook section, +// so that MallocHook::GetCallerStackTrace can function accurately: + +// Make sure mmap doesn't get #define'd away by <sys/mman.h> +# undef mmap + +extern "C" { + void* mmap64(void *start, size_t length, int prot, int flags, + int fd, __off64_t offset ) __THROW + ATTRIBUTE_SECTION(malloc_hook); + void* mmap(void *start, size_t length,int prot, int flags, + int fd, off_t offset) __THROW + ATTRIBUTE_SECTION(malloc_hook); + int munmap(void* start, size_t length) __THROW + ATTRIBUTE_SECTION(malloc_hook); + void* mremap(void* old_addr, size_t old_size, size_t new_size, + int flags, ...) __THROW + ATTRIBUTE_SECTION(malloc_hook); + void* sbrk(ptrdiff_t increment) __THROW + ATTRIBUTE_SECTION(malloc_hook); +} + +extern "C" void* mmap64(void *start, size_t length, int prot, int flags, + int fd, __off64_t offset) __THROW { + MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset); + void *result; + if (!MallocHook::InvokeMmapReplacement( + start, length, prot, flags, fd, offset, &result)) { + result = do_mmap64(start, length, prot, flags, fd, offset); + } + MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset); + return result; +} + +# if !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH) + +extern "C" void* mmap(void *start, size_t length, int prot, int flags, + int fd, off_t offset) __THROW { + MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset); + void *result; + if (!MallocHook::InvokeMmapReplacement( + start, length, prot, flags, fd, offset, &result)) { + result = do_mmap64(start, length, prot, flags, fd, + static_cast<size_t>(offset)); // avoid sign extension + } + MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset); + return result; +} + +# endif // !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH) + +extern "C" int munmap(void* start, size_t length) __THROW { + MallocHook::InvokeMunmapHook(start, length); + int result; + if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { + result = sys_munmap(start, length); + } + return result; +} + +extern "C" void* mremap(void* old_addr, size_t old_size, size_t new_size, + int flags, ...) __THROW { + va_list ap; + va_start(ap, flags); + void *new_address = va_arg(ap, void *); + va_end(ap); + void* result = sys_mremap(old_addr, old_size, new_size, flags, new_address); + MallocHook::InvokeMremapHook(result, old_addr, old_size, new_size, flags, + new_address); + return result; +} + +// libc's version: +extern "C" void* __sbrk(ptrdiff_t increment); + +extern "C" void* sbrk(ptrdiff_t increment) __THROW { + MallocHook::InvokePreSbrkHook(increment); + void *result = __sbrk(increment); + MallocHook::InvokeSbrkHook(result, increment); + return result; +} + +/*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot, + int flags, int fd, off_t offset) { + void* result; + if (!MallocHook::InvokeMmapReplacement( + start, length, prot, flags, fd, offset, &result)) { + result = do_mmap64(start, length, prot, flags, fd, offset); + } + return result; +} + +/*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) { + int result; + if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { + result = syscall(SYS_munmap, start, length); + } + return result; +} + +#undef MALLOC_HOOK_HAVE_DO_MMAP64 + +#endif // #ifdef MALLOC_HOOK_HAVE_DO_MMAP64 diff --git a/third_party/tcmalloc/vendor/src/maybe_threads.cc b/third_party/tcmalloc/vendor/src/maybe_threads.cc index cda1d63..15c8a23 100644 --- a/third_party/tcmalloc/vendor/src/maybe_threads.cc +++ b/third_party/tcmalloc/vendor/src/maybe_threads.cc @@ -39,6 +39,7 @@ #include "config.h" #include <assert.h> #include <string.h> // for memcmp +#include <stdio.h> // for __isthreaded on FreeBSD // We don't actually need strings. But including this header seems to // stop the compiler trying to short-circuit our pthreads existence // tests and claiming that the address of a function is always @@ -98,9 +99,28 @@ int perftools_pthread_setspecific(pthread_key_t key, void *val) { } } + static pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT; int perftools_pthread_once(pthread_once_t *ctl, void (*init_routine) (void)) { +#ifdef __FreeBSD__ + // On __FreeBSD__, calling pthread_once on a system that is not + // linked with -pthread is silently a noop. :-( Luckily, we have a + // workaround: FreeBSD exposes __isthreaded in <stdio.h>, which is + // set to 1 when the first thread is spawned. So on those systems, + // we can use our own separate pthreads-once mechanism, which is + // used until __isthreaded is 1 (which will never be true if the app + // is not linked with -pthread). + static bool pthread_once_ran_before_threads = false; + if (pthread_once_ran_before_threads) { + return 0; + } + if (!__isthreaded) { + init_routine(); + pthread_once_ran_before_threads = true; + return 0; + } +#endif if (pthread_once) { return pthread_once(ctl, init_routine); } else { diff --git a/third_party/tcmalloc/vendor/src/memfs_malloc.cc b/third_party/tcmalloc/vendor/src/memfs_malloc.cc index 3fb55a4..0bb27d7 100644 --- a/third_party/tcmalloc/vendor/src/memfs_malloc.cc +++ b/third_party/tcmalloc/vendor/src/memfs_malloc.cc @@ -58,7 +58,6 @@ #include "base/basictypes.h" #include "base/googleinit.h" #include "base/sysinfo.h" -#include "system-alloc.h" #include "internal_logging.h" using std::string; @@ -86,7 +85,7 @@ DEFINE_bool(memfs_malloc_map_private, class HugetlbSysAllocator: public SysAllocator { public: explicit HugetlbSysAllocator(SysAllocator* fallback) - : failed_(true), // Unusable until FlagsInitialized() is called + : failed_(true), // To disable allocator until Initialize() is called. big_page_size_(0), hugetlb_fd_(-1), hugetlb_base_(0), @@ -94,10 +93,10 @@ public: } void* Alloc(size_t size, size_t *actual_size, size_t alignment); - - void FlagsInitialized(); + bool Initialize(); bool failed_; // Whether failed to allocate memory. + private: void* AllocInternal(size_t size, size_t *actual_size, size_t alignment); @@ -212,49 +211,53 @@ void* HugetlbSysAllocator::AllocInternal(size_t size, size_t* actual_size, return reinterpret_cast<void*>(ptr); } -void HugetlbSysAllocator::FlagsInitialized() { - if (FLAGS_memfs_malloc_path.length()) { - char path[PATH_MAX]; - int rc = snprintf(path, sizeof(path), "%s.XXXXXX", - FLAGS_memfs_malloc_path.c_str()); - if (rc < 0 || rc >= sizeof(path)) { - CRASH("XX fatal: memfs_malloc_path too long\n"); - } - - int hugetlb_fd = mkstemp(path); - if (hugetlb_fd == -1) { - TCMalloc_MESSAGE(__FILE__, __LINE__, - "warning: unable to create memfs_malloc_path %s: %s\n", - path, strerror(errno)); - return; - } +bool HugetlbSysAllocator::Initialize() { + char path[PATH_MAX]; + int rc = snprintf(path, sizeof(path), "%s.XXXXXX", + FLAGS_memfs_malloc_path.c_str()); + if (rc < 0 || rc >= sizeof(path)) { + CRASH("XX fatal: memfs_malloc_path too long\n"); + return false; + } - // Cleanup memory on process exit - if (unlink(path) == -1) { - CRASH("fatal: error unlinking memfs_malloc_path %s: %s\n", - path, strerror(errno)); - } + int hugetlb_fd = mkstemp(path); + if (hugetlb_fd == -1) { + TCMalloc_MESSAGE(__FILE__, __LINE__, + "warning: unable to create memfs_malloc_path %s: %s\n", + path, strerror(errno)); + return false; + } - // Use fstatfs to figure out the default page size for memfs - struct statfs sfs; - if (fstatfs(hugetlb_fd, &sfs) == -1) { - CRASH("fatal: error fstatfs of memfs_malloc_path: %s\n", - strerror(errno)); - } - int64 page_size = sfs.f_bsize; + // Cleanup memory on process exit + if (unlink(path) == -1) { + CRASH("fatal: error unlinking memfs_malloc_path %s: %s\n", + path, strerror(errno)); + return false; + } - hugetlb_fd_ = hugetlb_fd; - big_page_size_ = page_size; - failed_ = false; + // Use fstatfs to figure out the default page size for memfs + struct statfs sfs; + if (fstatfs(hugetlb_fd, &sfs) == -1) { + CRASH("fatal: error fstatfs of memfs_malloc_path: %s\n", + strerror(errno)); + return false; } -} + int64 page_size = sfs.f_bsize; -static void InitSystemAllocator() { - SysAllocator *alloc = MallocExtension::instance()->GetSystemAllocator(); - HugetlbSysAllocator *hugetlb = new (hugetlb_space) HugetlbSysAllocator(alloc); - MallocExtension::instance()->SetSystemAllocator(hugetlb); + hugetlb_fd_ = hugetlb_fd; + big_page_size_ = page_size; + failed_ = false; + return true; } -REGISTER_MODULE_INITIALIZER(memfs_malloc, { InitSystemAllocator(); }); +REGISTER_MODULE_INITIALIZER(memfs_malloc, { + if (FLAGS_memfs_malloc_path.length()) { + SysAllocator* alloc = MallocExtension::instance()->GetSystemAllocator(); + HugetlbSysAllocator* hp = new (hugetlb_space) HugetlbSysAllocator(alloc); + if (hp->Initialize()) { + MallocExtension::instance()->SetSystemAllocator(hp); + } + } +}); #endif /* ifdef __linux */ diff --git a/third_party/tcmalloc/vendor/src/memory_region_map.cc b/third_party/tcmalloc/vendor/src/memory_region_map.cc index 3f17ac7..3bf8983 100644 --- a/third_party/tcmalloc/vendor/src/memory_region_map.cc +++ b/third_party/tcmalloc/vendor/src/memory_region_map.cc @@ -582,8 +582,8 @@ void MemoryRegionMap::MmapHook(const void* result, int fd, off_t offset) { // TODO(maxim): replace all 0x%"PRIxS" by %p when RAW_VLOG uses a safe // snprintf reimplementation that does not malloc to pretty-print NULL - RAW_VLOG(10, "MMap = 0x%"PRIxPTR" of %"PRIuS" at %llu " - "prot %d flags %d fd %d offs %lld", + RAW_VLOG(10, "MMap = 0x%"PRIxPTR" of %"PRIuS" at %"PRIu64" " + "prot %d flags %d fd %d offs %"PRId64, reinterpret_cast<uintptr_t>(result), size, reinterpret_cast<uint64>(start), prot, flags, fd, static_cast<int64>(offset)); diff --git a/third_party/tcmalloc/vendor/src/pprof b/third_party/tcmalloc/vendor/src/pprof index 03bafa4..0ce5df36 100644 --- a/third_party/tcmalloc/vendor/src/pprof +++ b/third_party/tcmalloc/vendor/src/pprof @@ -72,7 +72,7 @@ use strict; use warnings; use Getopt::Long; -my $PPROF_VERSION = "1.7"; +my $PPROF_VERSION = "1.8"; # These are the object tools we use which can come from a # user-specified location using --tools, from the PPROF_TOOLS @@ -156,7 +156,8 @@ pprof [options] <profile> The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile, $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall, $CENSUSPROFILE_PAGE, or /pprof/filteredprofile. - For instance: "pprof http://myserver.com:80$HEAP_PAGE". + For instance: + pprof http://myserver.com:80$HEAP_PAGE If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling). pprof --symbols <program> Maps addresses to symbol names. In this mode, stdin should be a @@ -545,7 +546,7 @@ sub Init() { ConfigureObjTools($main::prog) } - # Break the opt_list_prefix into the prefix_list array + # Break the opt_lib_prefix into the prefix_list array @prefix_list = split (',', $main::opt_lib_prefix); # Remove trailing / from the prefixes, in the list to prevent @@ -643,7 +644,7 @@ sub Main() { if ($main::opt_disasm) { PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm); } elsif ($main::opt_list) { - PrintListing($libs, $flat, $cumulative, $main::opt_list); + PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0); } elsif ($main::opt_text) { # Make sure the output is empty when have nothing to report # (only matters when --heapcheck is given but we must be @@ -839,7 +840,7 @@ sub InteractiveCommand { my $ignore; ($routine, $ignore) = ParseInteractiveArgs($3); - my $profile = ProcessProfile($orig_profile, $symbols, "", $ignore); + my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); my $reduced = ReduceProfile($symbols, $profile); # Get derived profiles @@ -866,21 +867,22 @@ sub InteractiveCommand { return 1; } - if (m/^\s*list\s*(.+)/) { + if (m/^\s*(web)?list\s*(.+)/) { + my $html = (defined($1) && ($1 eq "web")); $main::opt_list = 1; my $routine; my $ignore; - ($routine, $ignore) = ParseInteractiveArgs($1); + ($routine, $ignore) = ParseInteractiveArgs($2); - my $profile = ProcessProfile($orig_profile, $symbols, "", $ignore); + my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); my $reduced = ReduceProfile($symbols, $profile); # Get derived profiles my $flat = FlatProfile($reduced); my $cumulative = CumulativeProfile($reduced); - PrintListing($libs, $flat, $cumulative, $routine); + PrintListing($total, $libs, $flat, $cumulative, $routine, $html); return 1; } if (m/^\s*disasm\s*(.+)/) { @@ -891,7 +893,7 @@ sub InteractiveCommand { ($routine, $ignore) = ParseInteractiveArgs($1); # Process current profile to account for various settings - my $profile = ProcessProfile($orig_profile, $symbols, "", $ignore); + my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); my $reduced = ReduceProfile($symbols, $profile); # Get derived profiles @@ -918,7 +920,8 @@ sub InteractiveCommand { ($focus, $ignore) = ParseInteractiveArgs($2); # Process current profile to account for various settings - my $profile = ProcessProfile($orig_profile, $symbols, $focus, $ignore); + my $profile = ProcessProfile($total, $orig_profile, $symbols, + $focus, $ignore); my $reduced = ReduceProfile($symbols, $profile); # Get derived profiles @@ -946,6 +949,7 @@ sub InteractiveCommand { sub ProcessProfile { + my $total_count = shift; my $orig_profile = shift; my $symbols = shift; my $focus = shift; @@ -953,7 +957,6 @@ sub ProcessProfile { # Process current profile to account for various settings my $profile = $orig_profile; - my $total_count = TotalProfile($profile); printf("Total: %s %s\n", Unparse($total_count), Units()); if ($focus ne '') { $profile = FocusProfile($symbols, $profile, $focus); @@ -1000,6 +1003,11 @@ Commands: list [routine_regexp] [-ignore1] [-ignore2] Show source listing of routines whose names match "routine_regexp" + weblist [routine_regexp] [-ignore1] [-ignore2] + Displays a source listing of routines whose names match "routine_regexp" + in a web browser. You can click on source lines to view the + corresponding disassembly. + top [--cum] [-ignore1] [-ignore2] top20 [--cum] [-ignore1] [-ignore2] top37 [--cum] [-ignore1] [-ignore2] @@ -1175,7 +1183,7 @@ sub PrintText { $sym); } $lines++; - last if ($line_limit >= 0 && $lines > $line_limit); + last if ($line_limit >= 0 && $lines >= $line_limit); } } @@ -1322,13 +1330,33 @@ sub ByName { return ShortFunctionName($a) cmp ShortFunctionName($b); } -# Print source-listing for all all routines that match $main::opt_list +# Print source-listing for all all routines that match $list_opts sub PrintListing { + my $total = shift; my $libs = shift; my $flat = shift; my $cumulative = shift; my $list_opts = shift; + my $html = shift; + my $output = \*STDOUT; + my $fname = ""; + + if ($html) { + # Arrange to write the output to a temporary file + $fname = TempName($main::next_tmpfile, "html"); + $main::next_tmpfile++; + if (!open(TEMP, ">$fname")) { + print STDERR "$fname: $!\n"; + return; + } + $output = \*TEMP; + print $output HtmlListingHeader(); + printf $output ("<div class=\"legend\">%s<br>Total: %s %s</div>\n", + $main::prog, Unparse($total), Units()); + } + + my $listed = 0; foreach my $lib (@{$libs}) { my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts); my $offset = AddressSub($lib->[1], $lib->[3]); @@ -1340,15 +1368,113 @@ sub PrintListing { my $addr = AddressAdd($start_addr, $offset); for (my $i = 0; $i < $length; $i++) { if (defined($cumulative->{$addr})) { - PrintSource($lib->[0], $offset, - $routine, $flat, $cumulative, - $start_addr, $end_addr); + $listed += PrintSource( + $lib->[0], $offset, + $routine, $flat, $cumulative, + $start_addr, $end_addr, + $html, + $output); last; } $addr = AddressInc($addr); } } } + + if ($html) { + if ($listed > 0) { + print $output HtmlListingFooter(); + close($output); + RunWeb($fname); + } else { + close($output); + unlink($fname); + } + } +} + +sub HtmlListingHeader { + return <<'EOF'; +<DOCTYPE html> +<html> +<head> +<title>Pprof listing</title> +<style type="text/css"> +body { + font-family: sans-serif; +} +h1 { + font-size: 1.5em; + margin-bottom: 4px; +} +.legend { + font-size: 1.25em; +} +.line { + color: #aaaaaa; +} +.nop { + color: #aaaaaa; +} +.unimportant { + color: #cccccc; +} +.disasmloc { + color: #000000; +} +.deadsrc { + cursor: pointer; +} +.deadsrc:hover { + background-color: #eeeeee; +} +.livesrc { + color: #0000ff; + cursor: pointer; +} +.livesrc:hover { + background-color: #eeeeee; +} +.asm { + color: #008800; + display: none; +} +</style> +<script type="text/javascript"> +function pprof_toggle_asm(e) { + var target; + if (!e) e = window.event; + if (e.target) target = e.target; + else if (e.srcElement) target = e.srcElement; + + if (target) { + var asm = target.nextSibling; + if (asm && asm.className == "asm") { + asm.style.display = (asm.style.display == "block" ? "" : "block"); + e.preventDefault(); + return false; + } + } +} +</script> +</head> +<body> +EOF +} + +sub HtmlListingFooter { + return <<'EOF'; +</body> +</html> +EOF +} + +sub HtmlEscape { + my $text = shift; + $text =~ s/&/&/g; + $text =~ s/</</g; + $text =~ s/>/>/g; + return $text; } # Returns the indentation of the line, if it has any non-whitespace @@ -1362,6 +1488,45 @@ sub Indentation { } } +# If the symbol table contains inlining info, Disassemble() may tag an +# instruction with a location inside an inlined function. But for +# source listings, we prefer to use the location in the function we +# are listing. So use MapToSymbols() to fetch full location +# information for each instruction and then pick out the first +# location from a location list (location list contains callers before +# callees in case of inlining). +# +# After this routine has run, each entry in $instructions contains: +# [0] start address +# [1] filename for function we are listing +# [2] line number for function we are listing +# [3] disassembly +# [4] limit address +# [5] most specific filename (may be different from [1] due to inlining) +# [6] most specific line number (may be different from [2] due to inlining) +sub GetTopLevelLineNumbers { + my ($lib, $offset, $instructions) = @_; + my $pcs = []; + for (my $i = 0; $i <= $#{$instructions}; $i++) { + push(@{$pcs}, $instructions->[$i]->[0]); + } + my $symbols = {}; + MapToSymbols($lib, $offset, $pcs, $symbols); + for (my $i = 0; $i <= $#{$instructions}; $i++) { + my $e = $instructions->[$i]; + push(@{$e}, $e->[1]); + push(@{$e}, $e->[2]); + my $addr = $e->[0]; + my $sym = $symbols->{$addr}; + if (defined($sym)) { + if ($#{$sym} >= 2 && $sym->[1] =~ m/^(.*):(\d+)$/) { + $e->[1] = $1; # File name + $e->[2] = $2; # Line number + } + } + } +} + # Print source-listing for one routine sub PrintSource { my $prog = shift; @@ -1371,9 +1536,12 @@ sub PrintSource { my $cumulative = shift; my $start_addr = shift; my $end_addr = shift; + my $html = shift; + my $output = shift; # Disassemble all instructions (just to get line numbers) my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr); + GetTopLevelLineNumbers($prog, $offset, \@instructions); # Hack 1: assume that the first source file encountered in the # disassembly contains the routine @@ -1386,7 +1554,7 @@ sub PrintSource { } if (!defined($filename)) { print STDERR "no filename found in $routine\n"; - return; + return 0; } # Hack 2: assume that the largest line number from $filename is the @@ -1419,7 +1587,7 @@ sub PrintSource { { if (!open(FILE, "<$filename")) { print STDERR "$filename: $!\n"; - return; + return 0; } my $l = 0; my $first_indentation = -1; @@ -1447,12 +1615,24 @@ sub PrintSource { # Assign all samples to the range $firstline,$lastline, # Hack 4: If an instruction does not occur in the range, its samples # are moved to the next instruction that occurs in the range. - my $samples1 = {}; - my $samples2 = {}; - my $running1 = 0; # Unassigned flat counts - my $running2 = 0; # Unassigned cumulative counts - my $total1 = 0; # Total flat counts - my $total2 = 0; # Total cumulative counts + my $samples1 = {}; # Map from line number to flat count + my $samples2 = {}; # Map from line number to cumulative count + my $running1 = 0; # Unassigned flat counts + my $running2 = 0; # Unassigned cumulative counts + my $total1 = 0; # Total flat counts + my $total2 = 0; # Total cumulative counts + my %disasm = (); # Map from line number to disassembly + my $running_disasm = ""; # Unassigned disassembly + my $skip_marker = "---\n"; + if ($html) { + $skip_marker = ""; + for (my $l = $firstline; $l <= $lastline; $l++) { + $disasm{$l} = ""; + } + } + my $last_dis_filename = ''; + my $last_dis_linenum = -1; + my $last_touched_line = -1; # To detect gaps in disassembly for a line foreach my $e (@instructions) { # Add up counts for all address that fall inside this instruction my $c1 = 0; @@ -1461,6 +1641,38 @@ sub PrintSource { $c1 += GetEntry($flat, $a); $c2 += GetEntry($cumulative, $a); } + + if ($html) { + my $dis = sprintf(" %6s %6s \t\t%8s: %s ", + HtmlPrintNumber($c1), + HtmlPrintNumber($c2), + UnparseAddress($offset, $e->[0]), + CleanDisassembly($e->[3])); + + # Append the most specific source line associated with this instruction + if (length($dis) < 80) { $dis .= (' ' x (80 - length($dis))) }; + $dis = HtmlEscape($dis); + my $f = $e->[5]; + my $l = $e->[6]; + if ($f ne $last_dis_filename) { + $dis .= sprintf("<span class=disasmloc>%s:%d</span>", + HtmlEscape(CleanFileName($f)), $l); + } elsif ($l ne $last_dis_linenum) { + # De-emphasize the unchanged file name portion + $dis .= sprintf("<span class=unimportant>%s</span>" . + "<span class=disasmloc>:%d</span>", + HtmlEscape(CleanFileName($f)), $l); + } else { + # De-emphasize the entire location + $dis .= sprintf("<span class=unimportant>%s:%d</span>", + HtmlEscape(CleanFileName($f)), $l); + } + $last_dis_filename = $f; + $last_dis_linenum = $l; + $running_disasm .= $dis; + $running_disasm .= "\n"; + } + $running1 += $c1; $running2 += $c2; $total1 += $c1; @@ -1475,23 +1687,49 @@ sub PrintSource { AddEntry($samples2, $line, $running2); $running1 = 0; $running2 = 0; + if ($html) { + if ($line != $last_touched_line && $disasm{$line} ne '') { + $disasm{$line} .= "\n"; + } + $disasm{$line} .= $running_disasm; + $running_disasm = ''; + $last_touched_line = $line; + } } } # Assign any leftover samples to $lastline AddEntry($samples1, $lastline, $running1); AddEntry($samples2, $lastline, $running2); - - printf("ROUTINE ====================== %s in %s\n" . - "%6s %6s Total %s (flat / cumulative)\n", - ShortFunctionName($routine), - $filename, - Units(), - Unparse($total1), - Unparse($total2)); + if ($html) { + if ($lastline != $last_touched_line && $disasm{$lastline} ne '') { + $disasm{$lastline} .= "\n"; + } + $disasm{$lastline} .= $running_disasm; + } + + if ($html) { + printf $output ( + "<h1>%s</h1>%s\n<pre onClick=\"pprof_toggle_asm()\">\n" . + "Total:%6s %6s (flat / cumulative %s)\n", + HtmlEscape(ShortFunctionName($routine)), + HtmlEscape(CleanFileName($filename)), + Unparse($total1), + Unparse($total2), + Units()); + } else { + printf $output ( + "ROUTINE ====================== %s in %s\n" . + "%6s %6s Total %s (flat / cumulative)\n", + ShortFunctionName($routine), + CleanFileName($filename), + Unparse($total1), + Unparse($total2), + Units()); + } if (!open(FILE, "<$filename")) { print STDERR "$filename: $!\n"; - return; + return 0; } my $l = 0; while (<FILE>) { @@ -1501,16 +1739,47 @@ sub PrintSource { (($l <= $oldlastline + 5) || ($l <= $lastline))) { chop; my $text = $_; - if ($l == $firstline) { printf("---\n"); } - printf("%6s %6s %4d: %s\n", - UnparseAlt(GetEntry($samples1, $l)), - UnparseAlt(GetEntry($samples2, $l)), - $l, - $text); - if ($l == $lastline) { printf("---\n"); } + if ($l == $firstline) { print $output $skip_marker; } + my $n1 = GetEntry($samples1, $l); + my $n2 = GetEntry($samples2, $l); + if ($html) { + # Emit a span that has one of the following classes: + # livesrc -- has samples + # deadsrc -- has disassembly, but with no samples + # nop -- has no matching disasembly + # Also emit an optional span containing disassembly. + my $dis = $disasm{$l}; + my $asm = ""; + if (defined($dis) && $dis ne '') { + $asm = "<span class=\"asm\">" . $dis . "</span>"; + } + my $source_class = (($n1 + $n2 > 0) + ? "livesrc" + : (($asm ne "") ? "deadsrc" : "nop")); + printf $output ( + "<span class=\"line\">%5d</span> " . + "<span class=\"%s\">%6s %6s %s</span>%s\n", + $l, $source_class, + HtmlPrintNumber($n1), + HtmlPrintNumber($n2), + HtmlEscape($text), + $asm); + } else { + printf $output( + "%6s %6s %4d: %s\n", + UnparseAlt($n1), + UnparseAlt($n2), + $l, + $text); + } + if ($l == $lastline) { print $output $skip_marker; } }; } close(FILE); + if ($html) { + print $output "</pre>\n"; + } + return 1; } # Return the source line for the specified file/linenumber. @@ -1653,21 +1922,11 @@ sub PrintDisassembledFunction { # Print disassembly for (my $x = $first_inst; $x <= $last_inst; $x++) { my $e = $instructions[$x]; - my $address = $e->[0]; - $address = AddressSub($address, $offset); # Make relative to section - $address =~ s/^0x//; - $address =~ s/^0*//; - - # Trim symbols - my $d = $e->[3]; - while ($d =~ s/\([^()%]*\)(\s*const)?//g) { } # Argument types, not (%rax) - while ($d =~ s/(\w+)<[^<>]*>/$1/g) { } # Remove template arguments - printf("%6s %6s %8s: %6s\n", UnparseAlt($flat_count[$x]), UnparseAlt($cum_count[$x]), - $address, - $d); + UnparseAddress($offset, $e->[0]), + CleanDisassembly($e->[3])); } } } @@ -2326,6 +2585,16 @@ sub UnparseAlt { } } +# Alternate pretty-printed form: 0 maps to "" +sub HtmlPrintNumber { + my $num = shift; + if ($num == 0) { + return ""; + } else { + return Unparse($num); + } +} + # Return output units sub Units { if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { @@ -2482,6 +2751,13 @@ sub RemoveUninterestingFrames { '__builtin_vec_new', 'operator new', 'operator new[]', + # The entry to our memory-allocation routines on OS X + 'malloc_zone_malloc', + 'malloc_zone_calloc', + 'malloc_zone_valloc', + 'malloc_zone_realloc', + 'malloc_zone_memalign', + 'malloc_zone_free', # These mark the beginning/end of our custom sections '__start_google_malloc', '__stop_google_malloc', @@ -4414,6 +4690,31 @@ sub ShortFunctionName { return $function; } +# Trim overly long symbols found in disassembler output +sub CleanDisassembly { + my $d = shift; + while ($d =~ s/\([^()%]*\)(\s*const)?//g) { } # Argument types, not (%rax) + while ($d =~ s/(\w+)<[^<>]*>/$1/g) { } # Remove template arguments + return $d; +} + +# Clean file name for display +sub CleanFileName { + my ($f) = @_; + $f =~ s|^/proc/self/cwd/||; + $f =~ s|^\./||; + return $f; +} + +# Make address relative to section and clean up for display +sub UnparseAddress { + my ($offset, $address) = @_; + $address = AddressSub($address, $offset); + $address =~ s/^0x//; + $address =~ s/^0*//; + return $address; +} + ##### Miscellaneous ##### # Find the right versions of the above object tools to use. The diff --git a/third_party/tcmalloc/vendor/src/profile-handler.cc b/third_party/tcmalloc/vendor/src/profile-handler.cc index 1946f7c..700b5c0 100644 --- a/third_party/tcmalloc/vendor/src/profile-handler.cc +++ b/third_party/tcmalloc/vendor/src/profile-handler.cc @@ -36,7 +36,7 @@ #include "config.h" #include "profile-handler.h" -#if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) +#if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) && !defined(__native_client__) #include <stdio.h> #include <errno.h> @@ -478,12 +478,14 @@ extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) { ProfileHandler::Instance()->GetState(state); } -#else // OS_CYGWIN +#else // !defined(OS_CYGWIN) && !defined(__native_client__) // ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't // work as well for profiling, and also interferes with alarm(). Because of // these issues, unless a specific need is identified, profiler support is // disabled under Cygwin. +// +// Native Client runtime also does not have signals working. extern "C" void ProfileHandlerRegisterThread() { } @@ -501,4 +503,4 @@ extern "C" void ProfileHandlerReset() { extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) { } -#endif // OS_CYGWIN +#endif // !defined(OS_CYGWIN) && !defined(__native_client__) diff --git a/third_party/tcmalloc/vendor/src/profiler.cc b/third_party/tcmalloc/vendor/src/profiler.cc index 38fbb93..a57953e 100644 --- a/third_party/tcmalloc/vendor/src/profiler.cc +++ b/third_party/tcmalloc/vendor/src/profiler.cc @@ -284,7 +284,7 @@ void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext, } } -#if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) +#if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) && !defined(__native_client__) extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() { ProfileHandlerRegisterThread(); @@ -316,12 +316,14 @@ extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState( CpuProfiler::instance_.GetCurrentState(state); } -#else // OS_CYGWIN +#else // !defined(OS_CYGWIN) && !defined(__native_client__) // ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't // work as well for profiling, and also interferes with alarm(). Because of // these issues, unless a specific need is identified, profiler support is // disabled under Cygwin. +// +// Native Client runtime also does not have signals working. extern "C" void ProfilerRegisterThread() { } extern "C" void ProfilerFlush() { } extern "C" int ProfilingIsEnabledForAllThreads() { return 0; } @@ -335,7 +337,7 @@ extern "C" void ProfilerGetCurrentState(ProfilerState* state) { memset(state, 0, sizeof(*state)); } -#endif // OS_CYGWIN +#endif // !defined(OS_CYGWIN) && !defined(__native_client__) // DEPRECATED routines extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { } diff --git a/third_party/tcmalloc/vendor/src/stack_trace_table.h b/third_party/tcmalloc/vendor/src/stack_trace_table.h index e1d6a8a..26d21c1 100644 --- a/third_party/tcmalloc/vendor/src/stack_trace_table.h +++ b/third_party/tcmalloc/vendor/src/stack_trace_table.h @@ -36,7 +36,9 @@ #define TCMALLOC_STACK_TRACE_TABLE_H_ #include <config.h> +#ifdef HAVE_STDINT_H #include <stdint.h> // for uintptr_t +#endif #include "common.h" namespace tcmalloc { diff --git a/third_party/tcmalloc/vendor/src/stacktrace.cc b/third_party/tcmalloc/vendor/src/stacktrace.cc index 68cb865..175cdf5 100644 --- a/third_party/tcmalloc/vendor/src/stacktrace.cc +++ b/third_party/tcmalloc/vendor/src/stacktrace.cc @@ -99,11 +99,12 @@ #elif 0 // This is for the benefit of code analysis tools that may have // trouble with the computed #include above. -# include "base/stacktrace_x86-inl.h" -# include "base/stacktrace_libunwind-inl.h" -# include "base/stacktrace_generic-inl.h" -# include "base/stacktrace_powerpc-inl.h" -# include "base/stacktrace_win32-inl.h" +# include "stacktrace_x86-inl.h" +# include "stacktrace_libunwind-inl.h" +# include "stacktrace_generic-inl.h" +# include "stacktrace_powerpc-inl.h" +# include "stacktrace_nacl-inl.h" +# include "stacktrace_win32-inl.h" #else # error Cannot calculate stack trace: will need to write for your environment #endif diff --git a/third_party/tcmalloc/vendor/src/stacktrace_config.h b/third_party/tcmalloc/vendor/src/stacktrace_config.h index 18f16ab..b166ca2 100644 --- a/third_party/tcmalloc/vendor/src/stacktrace_config.h +++ b/third_party/tcmalloc/vendor/src/stacktrace_config.h @@ -46,8 +46,11 @@ #ifndef BASE_STACKTRACE_CONFIG_H_ #define BASE_STACKTRACE_CONFIG_H_ -// First, the i386 and x86_64 case. -#if (defined(__i386__) || defined(__x86_64__)) && __GNUC__ >= 2 +#ifdef __native_client__ +# define STACKTRACE_INL_HEADER "base/stacktrace_nacl-inl.h" + +// i386 and x86_64 case. +#elif (defined(__i386__) || defined(__x86_64__)) && __GNUC__ >= 2 # if !defined(NO_FRAME_POINTER) # define STACKTRACE_INL_HEADER "stacktrace_x86-inl.h" # define STACKTRACE_SKIP_CONTEXT_ROUTINES 1 diff --git a/third_party/tcmalloc/vendor/src/stacktrace_nacl-inl.h b/third_party/tcmalloc/vendor/src/stacktrace_nacl-inl.h new file mode 100644 index 0000000..7467e75 --- /dev/null +++ b/third_party/tcmalloc/vendor/src/stacktrace_nacl-inl.h @@ -0,0 +1,37 @@ +// Copyright (c) 2011, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 +// OWNER OR CONTRIBUTORS 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. + +// --- +// Author: Ivan Krasin +// +// Native Client stub for stacktrace. + +int GET_STACK_TRACE_OR_FRAMES { + return 0; +} diff --git a/third_party/tcmalloc/vendor/src/symbolize.cc b/third_party/tcmalloc/vendor/src/symbolize.cc index ff45e3e..dfdfb7e 100644 --- a/third_party/tcmalloc/vendor/src/symbolize.cc +++ b/third_party/tcmalloc/vendor/src/symbolize.cc @@ -48,6 +48,13 @@ #ifdef HAVE_POLL_H #include <poll.h> #endif +#ifdef __MACH__ +#include <mach-o/dyld.h> // for GetProgramInvocationName() +#include <limits.h> // for PATH_MAX +#endif +#if defined(__CYGWIN__) || defined(__CYGWIN32__) +#include <io.h> // for get_osfhandle() +#endif #include <string> #include "base/commandlineflags.h" #include "base/sysinfo.h" @@ -65,6 +72,27 @@ DEFINE_string(symbolize_pprof, // a more-permanent copy that won't ever get destroyed. static string* g_pprof_path = new string(FLAGS_symbolize_pprof); +// Returns NULL if we're on an OS where we can't get the invocation name. +// Using a static var is ok because we're not called from a thread. +static char* GetProgramInvocationName() { +#if defined(HAVE_PROGRAM_INVOCATION_NAME) + extern char* program_invocation_name; // gcc provides this + return program_invocation_name; +#elif defined(__MACH__) + // We don't want to allocate memory for this since we may be + // calculating it when memory is corrupted. + static char program_invocation_name[PATH_MAX]; + if (program_invocation_name[0] == '\0') { // first time calculating + uint32_t length = sizeof(program_invocation_name); + if (_NSGetExecutablePath(program_invocation_name, &length)) + return NULL; + } + return program_invocation_name; +#else + return NULL; // figure out a way to get argv[0] +#endif +} + void SymbolTable::Add(const void* addr) { symbolization_table_[addr] = ""; } @@ -82,11 +110,12 @@ const char* SymbolTable::GetSymbol(const void* addr) { int SymbolTable::Symbolize() { #if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS_WAIT_H) return 0; -#elif !defined(HAVE_PROGRAM_INVOCATION_NAME) - return 0; // TODO(csilvers): get argv[0] somehow #else + const char* argv0 = GetProgramInvocationName(); + if (argv0 == NULL) // can't call symbolize if we can't figure out our name + return 0; + // All this work is to do two-way communication. ugh. - extern char* program_invocation_name; // gcc provides this int *child_in = NULL; // file descriptors int *child_out = NULL; // for now, we don't worry about child_err int child_fds[5][2]; // socketpair may be called up to five times below @@ -142,7 +171,7 @@ int SymbolTable::Symbolize() { unsetenv("HEAPCHECK"); unsetenv("PERFTOOLS_VERBOSE"); execlp(g_pprof_path->c_str(), g_pprof_path->c_str(), - "--symbols", program_invocation_name, NULL); + "--symbols", argv0, NULL); _exit(3); // if execvp fails, it's bad news for us } default: { // parent @@ -159,7 +188,13 @@ int SymbolTable::Symbolize() { return 0; } #endif +#if defined(__CYGWIN__) || defined(__CYGWIN32__) + // On cygwin, DumpProcSelfMaps() takes a HANDLE, not an fd. Convert. + const HANDLE symbols_handle = (HANDLE) get_osfhandle(child_in[1]); + DumpProcSelfMaps(symbols_handle); +#else DumpProcSelfMaps(child_in[1]); // what pprof expects on stdin +#endif // Allocate 24 bytes = ("0x" + 8 bytes + "\n" + overhead) for each // address to feed to pprof. diff --git a/third_party/tcmalloc/vendor/src/system-alloc.cc b/third_party/tcmalloc/vendor/src/system-alloc.cc index 690953d..a05060a 100644 --- a/third_party/tcmalloc/vendor/src/system-alloc.cc +++ b/third_party/tcmalloc/vendor/src/system-alloc.cc @@ -133,7 +133,6 @@ public: SbrkSysAllocator() : SysAllocator() { } void* Alloc(size_t size, size_t *actual_size, size_t alignment); - void FlagsInitialized() {} }; static char sbrk_space[sizeof(SbrkSysAllocator)]; @@ -142,7 +141,6 @@ public: MmapSysAllocator() : SysAllocator() { } void* Alloc(size_t size, size_t *actual_size, size_t alignment); - void FlagsInitialized() {} }; static char mmap_space[sizeof(MmapSysAllocator)]; @@ -151,7 +149,6 @@ public: DevMemSysAllocator() : SysAllocator() { } void* Alloc(size_t size, size_t *actual_size, size_t alignment); - void FlagsInitialized() {} }; class DefaultSysAllocator : public SysAllocator { @@ -160,6 +157,7 @@ class DefaultSysAllocator : public SysAllocator { for (int i = 0; i < kMaxAllocators; i++) { failed_[i] = true; allocs_[i] = NULL; + names_[i] = NULL; } } void SetChildAllocator(SysAllocator* alloc, unsigned int index, @@ -167,10 +165,10 @@ class DefaultSysAllocator : public SysAllocator { if (index < kMaxAllocators && alloc != NULL) { allocs_[index] = alloc; failed_[index] = false; + names_[index] = name; } } void* Alloc(size_t size, size_t *actual_size, size_t alignment); - void FlagsInitialized() {} private: static const int kMaxAllocators = 2; diff --git a/third_party/tcmalloc/vendor/src/system-alloc.h b/third_party/tcmalloc/vendor/src/system-alloc.h index 487a36b..814b556 100644 --- a/third_party/tcmalloc/vendor/src/system-alloc.h +++ b/third_party/tcmalloc/vendor/src/system-alloc.h @@ -74,4 +74,4 @@ extern void TCMalloc_SystemRelease(void* start, size_t length); // The current system allocator. extern PERFTOOLS_DLL_DECL SysAllocator* sys_alloc; -#endif /* TCMALLOC_SYSTEM_ALLOC_H__ */ +#endif /* TCMALLOC_SYSTEM_ALLOC_H_ */ diff --git a/third_party/tcmalloc/vendor/src/tcmalloc.cc b/third_party/tcmalloc/vendor/src/tcmalloc.cc index 97c366c..263db81 100644 --- a/third_party/tcmalloc/vendor/src/tcmalloc.cc +++ b/third_party/tcmalloc/vendor/src/tcmalloc.cc @@ -93,9 +93,6 @@ #ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> // for __THROW #endif -#ifdef HAVE_FEATURES_H -#include <features.h> // for __GLIBC__ -#endif #if defined HAVE_STDINT_H #include <stdint.h> #elif defined HAVE_INTTYPES_H @@ -153,6 +150,17 @@ using STL_NAMESPACE::max; using STL_NAMESPACE::numeric_limits; using STL_NAMESPACE::vector; + +#include "libc_override.h" + +// __THROW is defined in glibc (via <sys/cdefs.h>). It means, +// counter-intuitively, "This function will never throw an exception." +// It's an optional optimization tool, but we may need to use it to +// match glibc prototypes. +#ifndef __THROW // I guess we're not on a glibc system +# define __THROW // __THROW is just an optimization, so ok to make it "" +#endif + using tcmalloc::AlignmentForSize; using tcmalloc::PageHeap; using tcmalloc::PageHeapAllocator; @@ -162,13 +170,6 @@ using tcmalloc::StackTrace; using tcmalloc::Static; using tcmalloc::ThreadCache; -// __THROW is defined in glibc systems. It means, counter-intuitively, -// "This function will never throw an exception." It's an optional -// optimization tool, but we may need to use it to match glibc prototypes. -#ifndef __THROW // I guess we're not on a glibc system -# define __THROW // __THROW is just an optimization, so ok to make it "" -#endif - DECLARE_int64(tcmalloc_sample_parameter); DECLARE_double(tcmalloc_release_rate); @@ -267,128 +268,6 @@ extern "C" { } // extern "C" #endif // #ifndef _WIN32 -// Override the libc functions to prefer our own instead. This comes -// first so code in tcmalloc.cc can use the overridden versions. One -// exception: in windows, by default, we patch our code into these -// functions (via src/windows/patch_function.cc) rather than override -// them. In that case, we don't want to do this overriding here. -#if !defined(WIN32_DO_PATCHING) - -#if defined(__GNUC__) && !defined(__MACH__) - // Potentially faster variants that use the gcc alias extension. - // FreeBSD does support aliases, but apparently not correctly. :-( - // NOTE: we make many of these symbols weak, but do so in the makefile - // (via objcopy -W) and not here. That ends up being more portable. -# define ALIAS(x) __attribute__ ((alias (x))) -void* operator new(size_t size) throw (std::bad_alloc) ALIAS("tc_new"); -void operator delete(void* p) __THROW ALIAS("tc_delete"); -void* operator new[](size_t size) throw (std::bad_alloc) ALIAS("tc_newarray"); -void operator delete[](void* p) __THROW ALIAS("tc_deletearray"); -void* operator new(size_t size, const std::nothrow_t&) __THROW - ALIAS("tc_new_nothrow"); -void* operator new[](size_t size, const std::nothrow_t&) __THROW - ALIAS("tc_newarray_nothrow"); -void operator delete(void* size, const std::nothrow_t&) __THROW - ALIAS("tc_delete_nothrow"); -void operator delete[](void* size, const std::nothrow_t&) __THROW - ALIAS("tc_deletearray_nothrow"); -extern "C" { - void* malloc(size_t size) __THROW ALIAS("tc_malloc"); - void free(void* ptr) __THROW ALIAS("tc_free"); - void* realloc(void* ptr, size_t size) __THROW ALIAS("tc_realloc"); - void* calloc(size_t n, size_t size) __THROW ALIAS("tc_calloc"); - void cfree(void* ptr) __THROW ALIAS("tc_cfree"); - void* memalign(size_t align, size_t s) __THROW ALIAS("tc_memalign"); - void* valloc(size_t size) __THROW ALIAS("tc_valloc"); - void* pvalloc(size_t size) __THROW ALIAS("tc_pvalloc"); - int posix_memalign(void** r, size_t a, size_t s) __THROW - ALIAS("tc_posix_memalign"); - void malloc_stats(void) __THROW ALIAS("tc_malloc_stats"); - int mallopt(int cmd, int value) __THROW ALIAS("tc_mallopt"); -#ifdef HAVE_STRUCT_MALLINFO - struct mallinfo mallinfo(void) __THROW ALIAS("tc_mallinfo"); -#endif - size_t malloc_size(void* p) __THROW ALIAS("tc_malloc_size"); - size_t malloc_usable_size(void* p) __THROW ALIAS("tc_malloc_size"); -} // extern "C" -#else // #if defined(__GNUC__) && !defined(__MACH__) -// Portable wrappers -void* operator new(size_t size) { return tc_new(size); } -void operator delete(void* p) __THROW { tc_delete(p); } -void* operator new[](size_t size) { return tc_newarray(size); } -void operator delete[](void* p) __THROW { tc_deletearray(p); } -void* operator new(size_t size, const std::nothrow_t& nt) __THROW { - return tc_new_nothrow(size, nt); -} -void* operator new[](size_t size, const std::nothrow_t& nt) __THROW { - return tc_newarray_nothrow(size, nt); -} -void operator delete(void* ptr, const std::nothrow_t& nt) __THROW { - return tc_delete_nothrow(ptr, nt); -} -void operator delete[](void* ptr, const std::nothrow_t& nt) __THROW { - return tc_deletearray_nothrow(ptr, nt); -} -extern "C" { - void* malloc(size_t s) __THROW { return tc_malloc(s); } - void free(void* p) __THROW { tc_free(p); } - void* realloc(void* p, size_t s) __THROW { return tc_realloc(p, s); } - void* calloc(size_t n, size_t s) __THROW { return tc_calloc(n, s); } - void cfree(void* p) __THROW { tc_cfree(p); } - void* memalign(size_t a, size_t s) __THROW { return tc_memalign(a, s); } - void* valloc(size_t s) __THROW { return tc_valloc(s); } - void* pvalloc(size_t s) __THROW { return tc_pvalloc(s); } - int posix_memalign(void** r, size_t a, size_t s) __THROW { - return tc_posix_memalign(r, a, s); - } - void malloc_stats(void) __THROW { tc_malloc_stats(); } - int mallopt(int cmd, int v) __THROW { return tc_mallopt(cmd, v); } -#ifdef HAVE_STRUCT_MALLINFO - struct mallinfo mallinfo(void) __THROW { return tc_mallinfo(); } -#endif - size_t malloc_size(void* p) __THROW { return tc_malloc_size(p); } - size_t malloc_usable_size(void* p) __THROW { return tc_malloc_size(p); } -} // extern "C" -#endif // #if defined(__GNUC__) - -// Some library routines on RedHat 9 allocate memory using malloc() -// and free it using __libc_free() (or vice-versa). Since we provide -// our own implementations of malloc/free, we need to make sure that -// the __libc_XXX variants (defined as part of glibc) also point to -// the same implementations. -#ifdef __GLIBC__ // only glibc defines __libc_* -extern "C" { -#ifdef ALIAS - void* __libc_malloc(size_t size) ALIAS("tc_malloc"); - void __libc_free(void* ptr) ALIAS("tc_free"); - void* __libc_realloc(void* ptr, size_t size) ALIAS("tc_realloc"); - void* __libc_calloc(size_t n, size_t size) ALIAS("tc_calloc"); - void __libc_cfree(void* ptr) ALIAS("tc_cfree"); - void* __libc_memalign(size_t align, size_t s) ALIAS("tc_memalign"); - void* __libc_valloc(size_t size) ALIAS("tc_valloc"); - void* __libc_pvalloc(size_t size) ALIAS("tc_pvalloc"); - int __posix_memalign(void** r, size_t a, size_t s) ALIAS("tc_posix_memalign"); -#else // #ifdef ALIAS - void* __libc_malloc(size_t size) { return malloc(size); } - void __libc_free(void* ptr) { free(ptr); } - void* __libc_realloc(void* ptr, size_t size) { return realloc(ptr, size); } - void* __libc_calloc(size_t n, size_t size) { return calloc(n, size); } - void __libc_cfree(void* ptr) { cfree(ptr); } - void* __libc_memalign(size_t align, size_t s) { return memalign(align, s); } - void* __libc_valloc(size_t size) { return valloc(size); } - void* __libc_pvalloc(size_t size) { return pvalloc(size); } - int __posix_memalign(void** r, size_t a, size_t s) { - return posix_memalign(r, a, s); - } -#endif // #ifdef ALIAS -} // extern "C" -#endif // ifdef __GLIBC__ - -#undef ALIAS - -#endif // #ifndef(WIN32_DO_PATCHING) - - // ----------------------- IMPLEMENTATION ------------------------------- static int tc_new_mode = 0; // See tc_set_new_mode(). @@ -430,9 +309,10 @@ static void ExtractStats(TCMallocStats* r, uint64_t* class_count) { for (int cl = 0; cl < kNumClasses; ++cl) { const int length = Static::central_cache()[cl].length(); const int tc_length = Static::central_cache()[cl].tc_length(); + const size_t cache_overhead = Static::central_cache()[cl].OverheadBytes(); const size_t size = static_cast<uint64_t>( Static::sizemap()->ByteSizeForClass(cl)); - r->central_bytes += (size * length); + r->central_bytes += (size * length) + cache_overhead; r->transfer_bytes += (size * tc_length); if (class_count) class_count[cl] = length + tc_length; } @@ -811,6 +691,25 @@ class TCMallocImplementation : public MallocExtension { // file. virtual size_t GetAllocatedSize(void* ptr); + // This duplicates some of the logic in GetSizeWithCallback, but is + // faster. This is important on OS X, where this function is called + // on every allocation operation. + virtual Ownership GetOwnership(const void* ptr) { + const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; + // The rest of tcmalloc assumes that all allocated pointers use at + // most kAddressBits bits. If ptr doesn't, then it definitely + // wasn't alloacted by tcmalloc. + if ((p >> (kAddressBits - kPageShift)) > 0) { + return kNotOwned; + } + size_t cl = Static::pageheap()->GetSizeClassIfCached(p); + if (cl != 0) { + return kOwned; + } + const Span *span = Static::pageheap()->GetDescriptor(p); + return span ? kOwned : kNotOwned; + } + virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) { static const char* kCentralCacheType = "tcmalloc.central"; static const char* kTransferCacheType = "tcmalloc.transfer"; @@ -924,9 +823,12 @@ TCMallocGuard::TCMallocGuard() { // Check whether the kernel also supports TLS (needs to happen at runtime) tcmalloc::CheckIfKernelSupportsTLS(); #endif -#ifdef WIN32_DO_PATCHING - // patch the windows VirtualAlloc, etc. - PatchWindowsFunctions(); // defined in windows/patch_functions.cc + ReplaceSystemAlloc(); // defined in libc_override_*.h +#if defined(__APPLE__) + // To break the recursive call of malloc, as malloc -> TCMALLOC_MESSAGE + // -> snprintf -> localeconv_l -> malloc, on MacOS. + char buf[32]; + snprintf(buf, sizeof(buf), "%d", tcmallocguard_refcount); #endif tc_free(tc_malloc(1)); ThreadCache::InitTSD(); @@ -1023,8 +925,8 @@ static void ReportLargeAlloc(Length num_pages, void* result) { static const int N = 1000; char buffer[N]; TCMalloc_Printer printer(buffer, N); - printer.printf("tcmalloc: large alloc %llu bytes == %p @ ", - static_cast<unsigned long long>(num_pages) << kPageShift, + printer.printf("tcmalloc: large alloc %"PRIu64" bytes == %p @ ", + static_cast<uint64>(num_pages) << kPageShift, result); for (int i = 0; i < stack.depth; i++) { printer.printf(" %p", stack.stack[i]); @@ -1184,6 +1086,8 @@ inline void do_free(void* ptr) { return do_free_with_callback(ptr, &InvalidFree); } +// NOTE: some logic here is duplicated in GetOwnership (above), for +// speed. If you change this function, look at that one too. inline size_t GetSizeWithCallback(void* ptr, size_t (*invalid_getsize_fn)(void*)) { if (ptr == NULL) @@ -1193,7 +1097,7 @@ inline size_t GetSizeWithCallback(void* ptr, if (cl != 0) { return Static::sizemap()->ByteSizeForClass(cl); } else { - Span *span = Static::pageheap()->GetDescriptor(p); + const Span *span = Static::pageheap()->GetDescriptor(p); if (span == NULL) { // means we do not own this memory return (*invalid_getsize_fn)(ptr); } else if (span->sizeclass != 0) { @@ -1476,6 +1380,8 @@ void* cpp_memalign(size_t align, size_t size) { // As promised, the definition of this function, declared above. size_t TCMallocImplementation::GetAllocatedSize(void* ptr) { + ASSERT(TCMallocImplementation::GetOwnership(ptr) + != TCMallocImplementation::kNotOwned); return GetSizeWithCallback(ptr, &InvalidGetAllocatedSize); } @@ -1673,26 +1579,7 @@ extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW { #endif extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW { - return GetSizeWithCallback(ptr, &InvalidGetAllocatedSize); -} - - -// Override __libc_memalign in libc on linux boxes specially. -// They have a bug in libc that causes them to (very rarely) allocate -// with __libc_memalign() yet deallocate with free() and the -// definitions above don't catch it. -// This function is an exception to the rule of calling MallocHook method -// from the stack frame of the allocation function; -// heap-checker handles this special case explicitly. -static void *MemalignOverride(size_t align, size_t size, const void *caller) - __THROW ATTRIBUTE_SECTION(google_malloc); - -static void *MemalignOverride(size_t align, size_t size, const void *caller) - __THROW { - void* result = do_memalign_or_cpp_memalign(align, size); - MallocHook::InvokeNewHook(result, size); - return result; + return MallocExtension::instance()->GetAllocatedSize(ptr); } -void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride; #endif // TCMALLOC_USING_DEBUGALLOCATION diff --git a/third_party/tcmalloc/vendor/src/tests/debugallocation_test.cc b/third_party/tcmalloc/vendor/src/tests/debugallocation_test.cc index 07b8604..cb458d4 100644 --- a/third_party/tcmalloc/vendor/src/tests/debugallocation_test.cc +++ b/third_party/tcmalloc/vendor/src/tests/debugallocation_test.cc @@ -75,7 +75,10 @@ static int test_counter = 0; // incremented every time the macro is called // This flag won't be compiled in in opt mode. DECLARE_int32(max_free_queue_size); -// Test match as well as mismatch rules: +// Test match as well as mismatch rules. But do not test on OS X; on +// OS X the OS converts new/new[] to malloc before it gets to us, so +// we are unable to catch these mismatch errors. +#ifndef __APPLE__ TEST(DebugAllocationTest, DeallocMismatch) { // malloc can be matched only by free // new can be matched only by delete and delete(nothrow) @@ -132,6 +135,7 @@ TEST(DebugAllocationTest, DeallocMismatch) { ::operator delete[](y, std::nothrow); } } +#endif // #ifdef OS_MACOSX TEST(DebugAllocationTest, DoubleFree) { int* pint = new int; diff --git a/third_party/tcmalloc/vendor/src/tests/malloc_extension_c_test.c b/third_party/tcmalloc/vendor/src/tests/malloc_extension_c_test.c index e384b76..57cdbbd 100644 --- a/third_party/tcmalloc/vendor/src/tests/malloc_extension_c_test.c +++ b/third_party/tcmalloc/vendor/src/tests/malloc_extension_c_test.c @@ -126,6 +126,14 @@ void TestMallocExtension(void) { if (MallocExtension_GetAllocatedSize(x) < 10) { FAIL("GetEstimatedAllocatedSize returned a bad value (too small)"); } + if (MallocExtension_GetOwnership(x) != MallocExtension_kOwned) { + FAIL("DidAllocatePtr returned a bad value (kNotOwned)"); + } + /* TODO(csilvers): this relies on undocumented behavior that + GetOwnership works on stack-allocated variables. Use a better test. */ + if (MallocExtension_GetOwnership(hist) != MallocExtension_kNotOwned) { + FAIL("DidAllocatePtr returned a bad value (kOwned)"); + } free(x); } diff --git a/third_party/tcmalloc/vendor/src/tests/malloc_extension_test.cc b/third_party/tcmalloc/vendor/src/tests/malloc_extension_test.cc index 0bd85ad..3e57765 100644 --- a/third_party/tcmalloc/vendor/src/tests/malloc_extension_test.cc +++ b/third_party/tcmalloc/vendor/src/tests/malloc_extension_test.cc @@ -55,6 +55,14 @@ int main(int argc, char** argv) { ASSERT_TRUE(MallocExtension::instance()->VerifyAllMemory()); ASSERT_TRUE(MallocExtension_VerifyAllMemory()); + ASSERT_EQ(MallocExtension::kOwned, + MallocExtension::instance()->GetOwnership(a)); + // TODO(csilvers): this relies on undocumented behavior that + // GetOwnership works on stack-allocated variables. Use a better test. + ASSERT_EQ(MallocExtension::kNotOwned, + MallocExtension::instance()->GetOwnership(&cxx_bytes_used)); + ASSERT_EQ(MallocExtension::kNotOwned, + MallocExtension::instance()->GetOwnership(NULL)); ASSERT_GE(MallocExtension::instance()->GetAllocatedSize(a), 1000); // This is just a sanity check. If we allocated too much, tcmalloc is broken ASSERT_LE(MallocExtension::instance()->GetAllocatedSize(a), 5000); @@ -68,12 +76,24 @@ int main(int argc, char** argv) { } // Check the c-shim version too. + ASSERT_EQ(MallocExtension_kOwned, MallocExtension_GetOwnership(a)); + ASSERT_EQ(MallocExtension_kNotOwned, + MallocExtension_GetOwnership(&cxx_bytes_used)); + ASSERT_EQ(MallocExtension_kNotOwned, MallocExtension_GetOwnership(NULL)); ASSERT_GE(MallocExtension_GetAllocatedSize(a), 1000); ASSERT_LE(MallocExtension_GetAllocatedSize(a), 5000); ASSERT_GE(MallocExtension_GetEstimatedAllocatedSize(1000), 1000); free(a); + // Verify that the .cc file and .h file have the same enum values. + ASSERT_EQ(static_cast<int>(MallocExtension::kUnknownOwnership), + static_cast<int>(MallocExtension_kUnknownOwnership)); + ASSERT_EQ(static_cast<int>(MallocExtension::kOwned), + static_cast<int>(MallocExtension_kOwned)); + ASSERT_EQ(static_cast<int>(MallocExtension::kNotOwned), + static_cast<int>(MallocExtension_kNotOwned)); + printf("DONE\n"); return 0; } diff --git a/third_party/tcmalloc/vendor/src/tests/malloc_hook_test.cc b/third_party/tcmalloc/vendor/src/tests/malloc_hook_test.cc index dc65b68..b46f6fd 100644 --- a/third_party/tcmalloc/vendor/src/tests/malloc_hook_test.cc +++ b/third_party/tcmalloc/vendor/src/tests/malloc_hook_test.cc @@ -36,16 +36,25 @@ #ifdef HAVE_MMAP #include <sys/mman.h> #endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> // for sleep() +#endif #include <algorithm> #include <string> #include <vector> #include <google/malloc_hook.h> #include "malloc_hook-inl.h" #include "base/logging.h" -#include "base/spinlock.h" +#include "base/simple_mutex.h" #include "base/sysinfo.h" #include "tests/testutil.h" +// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old +// form of the name instead. +#ifndef MAP_ANONYMOUS +# define MAP_ANONYMOUS MAP_ANON +#endif + namespace { using std::string; @@ -72,6 +81,15 @@ static int RUN_ALL_TESTS() { return 0; } +void Sleep(int seconds) { +#ifdef _MSC_VER + _sleep(seconds * 1000); // Windows's _sleep takes milliseconds argument +#else + sleep(seconds); +#endif +} + +using std::min; using base::internal::kHookListMaxValues; // Since HookList is a template and is defined in malloc_hook.cc, we can only @@ -81,7 +99,7 @@ typedef base::internal::HookList<MallocHook::NewHook> TestHookList; int TestHookList_Traverse(const TestHookList& list, int* output_array, int n) { MallocHook::NewHook values_as_hooks[kHookListMaxValues]; - int result = list.Traverse(values_as_hooks, std::min(n, kHookListMaxValues)); + int result = list.Traverse(values_as_hooks, min(n, kHookListMaxValues)); for (int i = 0; i < result; ++i) { output_array[i] = reinterpret_cast<const int&>(values_as_hooks[i]); } @@ -229,12 +247,12 @@ void MultithreadedTestThread(TestHookList* list, int shift, static volatile int num_threads_remaining; static TestHookList list = INIT_HOOK_LIST(69); -static SpinLock threadcount_lock; +static Mutex threadcount_lock; void MultithreadedTestThreadRunner(int thread_num) { // Wait for all threads to start running. { - SpinLockHolder h(&threadcount_lock); + MutexLock ml(&threadcount_lock); assert(num_threads_remaining > 0); --num_threads_remaining; @@ -242,7 +260,7 @@ void MultithreadedTestThreadRunner(int thread_num) { // go simple and busy-wait. while (num_threads_remaining > 0) { threadcount_lock.Unlock(); - SleepForMilliseconds(100); + Sleep(1); threadcount_lock.Lock(); } } @@ -271,7 +289,10 @@ TEST(HookListTest, MultithreadedTest) { EXPECT_EQ(0, list.priv_end); } -#ifdef HAVE_MMAP +// We only do mmap-hooking on (some) linux systems. +#if defined(HAVE_MMAP) && defined(__linux) && \ + (defined(__i386__) || defined(__x86_64__) || defined(__PPC__)) + int mmap_calls = 0; int mmap_matching_calls = 0; int munmap_calls = 0; @@ -336,7 +357,7 @@ TEST(MallocMookTest, MmapReplacements) { // whoever owns that memory now. // EXPECT_DEATH(*ptr = 'a', "SIGSEGV"); } -#endif // #ifdef HAVE_MMAN +#endif // #ifdef HAVE_MMAP && linux && ... } // namespace diff --git a/third_party/tcmalloc/vendor/src/tests/profiler_unittest.cc b/third_party/tcmalloc/vendor/src/tests/profiler_unittest.cc index 19371b7..fafc76f 100644 --- a/third_party/tcmalloc/vendor/src/tests/profiler_unittest.cc +++ b/third_party/tcmalloc/vendor/src/tests/profiler_unittest.cc @@ -61,7 +61,7 @@ static void test_other_thread() { for (i = 0; i < g_iters; ++i ) { result ^= i; } - snprintf(b, sizeof(b), "%d", result); // get some libc action + snprintf(b, sizeof(b), "other: %d", result); // get some libc action } #endif } @@ -74,7 +74,7 @@ static void test_main_thread() { for (i = 0; i < g_iters; ++i ) { result ^= i; } - snprintf(b, sizeof(b), "%d", result); // get some libc action + snprintf(b, sizeof(b), "same: %d", result); // get some libc action } } diff --git a/third_party/tcmalloc/vendor/src/tests/system-alloc_unittest.cc b/third_party/tcmalloc/vendor/src/tests/system-alloc_unittest.cc index c006425..8e4eb36 100644 --- a/third_party/tcmalloc/vendor/src/tests/system-alloc_unittest.cc +++ b/third_party/tcmalloc/vendor/src/tests/system-alloc_unittest.cc @@ -40,6 +40,7 @@ #endif #include <sys/types.h> #include <algorithm> +#include <limits> #include "base/logging.h" // for Check_GEImpl, Check_LTImpl, etc #include <google/malloc_extension.h> // for MallocExtension::instance #include "common.h" // for kAddressBits @@ -83,7 +84,6 @@ public: void DumpStats() { } - void FlagsInitialized() {} private: static const int kArraySize = 8 * 1024 * 1024; @@ -115,14 +115,30 @@ TEST(AddressBits, CpuVirtualBits) { const int kPointerBits = 8 * sizeof(void*); const int kImplementedVirtualBits = NumImplementedVirtualBits(); - CHECK_GE(kAddressBits, min(kImplementedVirtualBits, kPointerBits)); + CHECK_GE(kAddressBits, std::min(kImplementedVirtualBits, kPointerBits)); } #endif static void TestBasicRetryFailTest() { // Check with the allocator still works after a failed allocation. - void* p = malloc(1ULL << 50); // Asking for 1P ram - CHECK(p == NULL); + // + // There is no way to call malloc and guarantee it will fail. malloc takes a + // size_t parameter and the C++ standard does not constrain the size of + // size_t. For example, consider an implementation where size_t is 32 bits + // and pointers are 64 bits. + // + // It is likely, though, that sizeof(size_t) == sizeof(void*). In that case, + // the first allocation here might succeed but the second allocation must + // fail. + // + // If the second allocation succeeds, you will have to rewrite or + // disable this test. + // The weird parens are to avoid macro-expansion of 'max' on windows. + const size_t kHugeSize = (std::numeric_limits<size_t>::max)() / 2; + void* p1 = malloc(kHugeSize); + void* p2 = malloc(kHugeSize); + CHECK(p2 == NULL); + if (p1 != NULL) free(p1); char* q = new char[1024]; CHECK(q != NULL); diff --git a/third_party/tcmalloc/vendor/src/tests/tcmalloc_unittest.cc b/third_party/tcmalloc/vendor/src/tests/tcmalloc_unittest.cc index b430460..84a5889 100644 --- a/third_party/tcmalloc/vendor/src/tests/tcmalloc_unittest.cc +++ b/third_party/tcmalloc/vendor/src/tests/tcmalloc_unittest.cc @@ -96,16 +96,45 @@ // Windows doesn't define pvalloc and a few other obsolete unix // functions; nor does it define posix_memalign (which is not obsolete). -#if defined(_MSC_VER) || defined(__MINGW32__) +#if defined(_WIN32) # define cfree free // don't bother to try to test these obsolete fns # define valloc malloc # define pvalloc malloc // I'd like to map posix_memalign to _aligned_malloc, but _aligned_malloc // must be paired with _aligned_free (not normal free), which is too // invasive a change to how we allocate memory here. So just bail -# include <errno.h> -# define memalign(alignment, size) malloc(size) -# define posix_memalign(pptr, align, size) ((*(pptr)=malloc(size)) ? 0 : ENOMEM) +static bool kOSSupportsMemalign = false; +static inline void* Memalign(size_t align, size_t size) { + //LOG(FATAL) << "memalign not supported on windows"; + exit(1); +} +static inline int PosixMemalign(void** ptr, size_t align, size_t size) { + //LOG(FATAL) << "posix_memalign not supported on windows"; + exit(1); +} + +// OS X defines posix_memalign in some OS versions but not others; +// it's confusing enough to check that it's easiest to just not to test. +#elif defined(__APPLE__) +static bool kOSSupportsMemalign = false; +static inline void* Memalign(size_t align, size_t size) { + //LOG(FATAL) << "memalign not supported on OS X"; + exit(1); +} +static inline int PosixMemalign(void** ptr, size_t align, size_t size) { + //LOG(FATAL) << "posix_memalign not supported on OS X"; + exit(1); +} + +#else +static bool kOSSupportsMemalign = true; +static inline void* Memalign(size_t align, size_t size) { + return memalign(align, size); +} +static inline int PosixMemalign(void** ptr, size_t align, size_t size) { + return posix_memalign(ptr, align, size); +} + #endif // On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old @@ -149,7 +178,12 @@ static const size_t kMaxSize = ~static_cast<size_t>(0); static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1); static const size_t kNotTooBig = 100000; -static const size_t kTooBig = kMaxSize; +// We want an allocation that is definitely more than main memory. OS +// X has special logic to discard very big allocs before even passing +// the request along to the user-defined memory allocator; we're not +// interested in testing their logic, so we have to make sure we're +// not *too* big. +static const size_t kTooBig = kMaxSize - 100000; static int news_handled = 0; @@ -246,16 +280,18 @@ int TestHarness::PickType() { class AllocatorState : public TestHarness { public: - explicit AllocatorState(int seed) : TestHarness(seed) { - CHECK_GE(FLAGS_memalign_max_fraction, 0); - CHECK_LE(FLAGS_memalign_max_fraction, 1); - CHECK_GE(FLAGS_memalign_min_fraction, 0); - CHECK_LE(FLAGS_memalign_min_fraction, 1); - double delta = FLAGS_memalign_max_fraction - FLAGS_memalign_min_fraction; - CHECK_GE(delta, 0); - memalign_fraction_ = (Uniform(10000)/10000.0 * delta + - FLAGS_memalign_min_fraction); - //fprintf(LOGSTREAM, "memalign fraction: %f\n", memalign_fraction_); + explicit AllocatorState(int seed) : TestHarness(seed), memalign_fraction_(0) { + if (kOSSupportsMemalign) { + CHECK_GE(FLAGS_memalign_max_fraction, 0); + CHECK_LE(FLAGS_memalign_max_fraction, 1); + CHECK_GE(FLAGS_memalign_min_fraction, 0); + CHECK_LE(FLAGS_memalign_min_fraction, 1); + double delta = FLAGS_memalign_max_fraction - FLAGS_memalign_min_fraction; + CHECK_GE(delta, 0); + memalign_fraction_ = (Uniform(10000)/10000.0 * delta + + FLAGS_memalign_min_fraction); + //fprintf(LOGSTREAM, "memalign fraction: %f\n", memalign_fraction_); + } } virtual ~AllocatorState() {} @@ -269,7 +305,7 @@ class AllocatorState : public TestHarness { (size < sizeof(intptr_t) || alignment < FLAGS_memalign_max_alignment_ratio * size)) { void *result = reinterpret_cast<void*>(static_cast<intptr_t>(0x1234)); - int err = posix_memalign(&result, alignment, size); + int err = PosixMemalign(&result, alignment, size); if (err != 0) { CHECK_EQ(err, ENOMEM); } @@ -891,44 +927,42 @@ static void OnNoMemory() { static void TestSetNewMode() { int old_mode = tc_set_new_mode(1); - // DebugAllocation will try to catch huge allocations. We need to avoid this - // by requesting a smaller malloc block, that still can't be satisfied. - const size_t kHugeRequest = kTooBig - 1024; - - g_old_handler = std::set_new_handler(&OnNoMemory); - g_no_memory = false; - void* ret = malloc(kHugeRequest); - EXPECT_EQ(NULL, ret); - EXPECT_TRUE(g_no_memory); - g_old_handler = std::set_new_handler(&OnNoMemory); g_no_memory = false; - ret = calloc(1, kHugeRequest); + void* ret = malloc(kTooBig); EXPECT_EQ(NULL, ret); EXPECT_TRUE(g_no_memory); g_old_handler = std::set_new_handler(&OnNoMemory); g_no_memory = false; - ret = realloc(NULL, kHugeRequest); + ret = calloc(1, kTooBig); EXPECT_EQ(NULL, ret); EXPECT_TRUE(g_no_memory); - // Not really important, but must be small enough such that kAlignment + - // kHugeRequest does not overflow. - const int kAlignment = 1 << 5; - g_old_handler = std::set_new_handler(&OnNoMemory); g_no_memory = false; - ret = memalign(kAlignment, kHugeRequest); + ret = realloc(NULL, kTooBig); EXPECT_EQ(NULL, ret); EXPECT_TRUE(g_no_memory); - g_old_handler = std::set_new_handler(&OnNoMemory); - g_no_memory = false; - EXPECT_EQ(ENOMEM, - posix_memalign(&ret, kAlignment, kHugeRequest)); - EXPECT_EQ(NULL, ret); - EXPECT_TRUE(g_no_memory); + if (kOSSupportsMemalign) { + // Not really important, but must be small enough such that + // kAlignment + kTooBig does not overflow. + const int kAlignment = 1 << 5; + + g_old_handler = std::set_new_handler(&OnNoMemory); + g_no_memory = false; + ret = Memalign(kAlignment, kTooBig); + EXPECT_EQ(NULL, ret); + EXPECT_TRUE(g_no_memory); + + g_old_handler = std::set_new_handler(&OnNoMemory); + g_no_memory = false; + EXPECT_EQ(ENOMEM, + PosixMemalign(&ret, kAlignment, kTooBig)); + EXPECT_EQ(NULL, ret); + EXPECT_TRUE(g_no_memory); + } tc_set_new_mode(old_mode); } @@ -1032,17 +1066,19 @@ static int RunAllTests(int argc, char** argv) { cfree(p1); // synonym for free VerifyDeleteHookWasCalled(); - CHECK_EQ(posix_memalign(&p1, sizeof(p1), 40), 0); - CHECK(p1 != NULL); - VerifyNewHookWasCalled(); - free(p1); - VerifyDeleteHookWasCalled(); - - p1 = memalign(sizeof(p1) * 2, 50); - CHECK(p1 != NULL); - VerifyNewHookWasCalled(); - free(p1); - VerifyDeleteHookWasCalled(); + if (kOSSupportsMemalign) { + CHECK_EQ(PosixMemalign(&p1, sizeof(p1), 40), 0); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + free(p1); + VerifyDeleteHookWasCalled(); + + p1 = Memalign(sizeof(p1) * 2, 50); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + free(p1); + VerifyDeleteHookWasCalled(); + } // Windows has _aligned_malloc. Let's test that that's captured too. #if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(PERFTOOLS_NO_ALIGNED_MALLOC) diff --git a/third_party/tcmalloc/vendor/src/thread_cache.cc b/third_party/tcmalloc/vendor/src/thread_cache.cc index b00e3b4..c228c0f 100644 --- a/third_party/tcmalloc/vendor/src/thread_cache.cc +++ b/third_party/tcmalloc/vendor/src/thread_cache.cc @@ -46,8 +46,9 @@ DEFINE_int64(tcmalloc_max_total_thread_cache_bytes, EnvToInt64("TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES", kDefaultOverallThreadCacheSize), "Bound on the total amount of bytes allocated to " - "thread caches. This bound is not strict, so it is possible " - "for the cache to go over this bound in certain circumstances. "); + "thread caches. This bound is not strict, so it is possible " + "for the cache to go over this bound in certain circumstances. " + "Maximum value of this flag is capped to 1 GB."); namespace tcmalloc { @@ -72,7 +73,11 @@ pthread_key_t ThreadCache::heap_key_; #if defined(HAVE_TLS) bool kernel_supports_tls = false; // be conservative -# if !HAVE_DECL_UNAME // if too old for uname, probably too old for TLS +# if defined(_WIN32) // windows has supported TLS since winnt, I think. + void CheckIfKernelSupportsTLS() { + kernel_supports_tls = true; + } +# elif !HAVE_DECL_UNAME // if too old for uname, probably too old for TLS void CheckIfKernelSupportsTLS() { kernel_supports_tls = false; } @@ -313,6 +318,18 @@ void ThreadCache::InitTSD() { ASSERT(!tsd_inited_); perftools_pthread_key_create(&heap_key_, DestroyThreadCache); tsd_inited_ = true; + +#ifdef PTHREADS_CRASHES_IF_RUN_TOO_EARLY + // We may have used a fake pthread_t for the main thread. Fix it. + pthread_t zero; + memset(&zero, 0, sizeof(zero)); + SpinLockHolder h(Static::pageheap_lock()); + for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) { + if (h->tid_ == zero) { + h->tid_ = pthread_self(); + } + } +#endif } ThreadCache* ThreadCache::CreateCacheIfNecessary() { @@ -320,17 +337,23 @@ ThreadCache* ThreadCache::CreateCacheIfNecessary() { ThreadCache* heap = NULL; { SpinLockHolder h(Static::pageheap_lock()); - // On very old libc's, this call may crash if it happens too - // early. No libc using NPTL should be affected. If there - // is a crash here, we could use code (on linux, at least) - // to detect NPTL vs LinuxThreads: - // http://www.redhat.com/archives/phil-list/2003-April/msg00038.html - // If we detect not-NPTL, we could execute the old code from - // http://google-perftools.googlecode.com/svn/tags/google-perftools-1.7/src/thread_cache.cc - // that avoids calling pthread_self too early. The problem with - // that code is it caused a race condition when tcmalloc is linked - // in statically and other libraries spawn threads before main. + // On some old glibc's, and on freebsd's libc (as of freebsd 8.1), + // calling pthread routines (even pthread_self) too early could + // cause a segfault. Since we can call pthreads quite early, we + // have to protect against that in such situations by making a + // 'fake' pthread. This is not ideal since it doesn't work well + // when linking tcmalloc statically with apps that create threads + // before main, so we only do it if we have to. +#ifdef PTHREADS_CRASHES_IF_RUN_TOO_EARLY + pthread_t me; + if (!tsd_inited_) { + memset(&me, 0, sizeof(me)); + } else { + me = pthread_self(); + } +#else const pthread_t me = pthread_self(); +#endif // This may be a recursive malloc call from pthread_setspecific() // In that case, the heap for this thread has already been created @@ -474,7 +497,7 @@ void ThreadCache::PrintThreads(TCMalloc_Printer* out) { h->Print(out); actual_limit += h->max_size_; } - out->printf("ThreadCache overall: %"PRIuS ", unclaimed: %"PRIuS + out->printf("ThreadCache overall: %"PRIuS ", unclaimed: %"PRIdS ", actual: %"PRIuS"\n", overall_thread_cache_size_, unclaimed_cache_space_, actual_limit); } diff --git a/third_party/tcmalloc/vendor/src/windows/config.h b/third_party/tcmalloc/vendor/src/windows/config.h index 1d93c4f..7a7a8d7 100644 --- a/third_party/tcmalloc/vendor/src/windows/config.h +++ b/third_party/tcmalloc/vendor/src/windows/config.h @@ -94,6 +94,9 @@ /* Define to 1 if you have the <malloc.h> header file. */ #define HAVE_MALLOC_H 1 +/* Define to 1 if you have the <malloc/malloc.h> header file. */ +#undef HAVE_MALLOC_MALLOC_H + /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H @@ -136,6 +139,12 @@ /* Define to 1 if the system has the type `struct mallinfo'. */ #undef HAVE_STRUCT_MALLINFO +/* Define to 1 if you have the <sys/cdefs.h> header file. */ +#undef HAVE_SYS_CDEFS_H + +/* Define to 1 if you have the <sys/malloc.h> header file. */ +#undef HAVE_SYS_MALLOC_H + /* Define to 1 if you have the <sys/param.h> header file. */ #undef HAVE_SYS_PARAM_H @@ -197,6 +206,9 @@ */ #undef LT_OBJDIR +/* Define to 'volatile' if __malloc_hook is declared volatile */ +#undef MALLOC_HOOK_MAYBE_VOLATILE + /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O @@ -210,7 +222,7 @@ #define PACKAGE_NAME "google-perftools" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "google-perftools 1.7" +#define PACKAGE_STRING "google-perftools 1.8" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "google-perftools" @@ -219,7 +231,7 @@ #undef PACKAGE_URL /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.7" +#define PACKAGE_VERSION "1.8" /* How to access the PC from a struct ucontext */ #undef PC_FROM_UCONTEXT @@ -244,6 +256,12 @@ /* printf format code for printing a size_t and ssize_t */ #define PRIxS "Ix" +/* Mark the systems where we know it's bad if pthreads runs too + early before main (before threads are initialized, presumably). */ +#ifdef __FreeBSD__ +#define PTHREADS_CRASHES_IF_RUN_TOO_EARLY 1 +#endif + /* Define to necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE diff --git a/third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h.in b/third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h.in index a031b35..0b53e4e 100644 --- a/third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h.in +++ b/third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h.in @@ -35,6 +35,11 @@ #ifndef TCMALLOC_TCMALLOC_H_ #define TCMALLOC_TCMALLOC_H_ +#include <stddef.h> // for size_t +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> // where glibc defines __THROW +#endif + // __THROW is defined in glibc systems. It means, counter-intuitively, // "This function will never throw an exception." It's an optional // optimization tool, but we may need to use it to match glibc prototypes. @@ -60,7 +65,9 @@ #endif #ifdef __cplusplus -#include <new> // for std::nothrow_t +namespace std { +struct nothrow_t; +} extern "C" { #endif diff --git a/third_party/tcmalloc/vendor/src/windows/mingw.h b/third_party/tcmalloc/vendor/src/windows/mingw.h index 747b285..2aa5eb3 100644 --- a/third_party/tcmalloc/vendor/src/windows/mingw.h +++ b/third_party/tcmalloc/vendor/src/windows/mingw.h @@ -53,8 +53,6 @@ # define _WIN32_WINNT 0x0501 #endif -#include "windows/port.h" - #define HAVE_SNPRINTF 1 // Some mingw distributions have a pthreads wrapper, but it doesn't @@ -62,6 +60,8 @@ // pretend the pthreads wrapper doesn't exist, even when it does. #undef HAVE_PTHREAD +#include "windows/port.h" + #endif /* __MINGW32__ */ #endif /* GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_ */ diff --git a/third_party/tcmalloc/vendor/src/windows/port.cc b/third_party/tcmalloc/vendor/src/windows/port.cc index 1ecdace..e68de16 100644 --- a/third_party/tcmalloc/vendor/src/windows/port.cc +++ b/third_party/tcmalloc/vendor/src/windows/port.cc @@ -44,6 +44,7 @@ #include "port.h" #include "base/logging.h" #include "base/spinlock.h" +#include "internal_logging.h" #include "system-alloc.h" // ----------------------------------------------------------------------- @@ -265,6 +266,9 @@ void DumpSystemAllocatorStats(TCMalloc_Printer* printer) { // We don't dump stats on windows, right now } +// The current system allocator +SysAllocator* sys_alloc = NULL; + // ----------------------------------------------------------------------- // These functions rework existing functions of the same name in the diff --git a/third_party/tcmalloc/vendor/src/windows/port.h b/third_party/tcmalloc/vendor/src/windows/port.h index 0faba01..300c72d 100644 --- a/third_party/tcmalloc/vendor/src/windows/port.h +++ b/third_party/tcmalloc/vendor/src/windows/port.h @@ -165,6 +165,10 @@ EXTERN_C int perftools_pthread_once(pthread_once_t *once_control, #endif /* __cplusplus */ #endif /* HAVE_PTHREAD */ +inline void sched_yield(void) { + Sleep(0); +} + /* * __declspec(thread) isn't usable in a dll opened via LoadLibrary(). * But it doesn't work to LoadLibrary() us anyway, because of all the @@ -260,7 +264,7 @@ class SpinLockHolder { // Acquires a spinlock for as long as the scope lasts #define MAP_PRIVATE MEM_COMMIT #define MAP_SHARED MEM_RESERVE /* value of this #define is 100% arbitrary */ -#if __STDC__ +#if __STDC__ && !defined(__MINGW32__) typedef _off_t off_t; #endif @@ -372,7 +376,6 @@ inline char *getcwd(char *buf, size_t size) { inline int mkdir(const char *pathname, int) { return _mkdir(pathname); } -#endif inline FILE *popen(const char *command, const char *type) { return _popen(command, type); @@ -380,13 +383,14 @@ inline FILE *popen(const char *command, const char *type) { inline int pclose(FILE *stream) { return _pclose(stream); } +#endif EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len); /* ----------------------------------- SYSTEM/PROCESS */ typedef int pid_t; -#if __STDC__ +#if __STDC__ && !defined(__MINGW32__) inline pid_t getpid(void) { return _getpid(); } #endif inline pid_t getppid(void) { return 0; } |