summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morrow <acm@mongodb.com>2019-04-09 12:39:25 -0400
committerAndrew Morrow <acm@mongodb.com>2019-04-09 12:56:08 -0400
commitba963c9a88eda87942926e6b17901f8c00bd46d0 (patch)
treea6b363beb08f242415229508f888640bedf25d82
parentdecf670a6d7ec7a31c3820032188aab3fdc0fbd1 (diff)
downloadmongo-ba963c9a88eda87942926e6b17901f8c00bd46d0.tar.gz
SERVER-40375 Remove gperftools 2.5
-rw-r--r--src/third_party/SConscript10
-rw-r--r--src/third_party/gperftools-2.5/AUTHORS2
-rw-r--r--src/third_party/gperftools-2.5/COPYING28
-rw-r--r--src/third_party/gperftools-2.5/ChangeLog646
-rw-r--r--src/third_party/gperftools-2.5/INSTALL563
-rw-r--r--src/third_party/gperftools-2.5/NEWS724
-rw-r--r--src/third_party/gperftools-2.5/README283
-rw-r--r--src/third_party/gperftools-2.5/README_windows.txt120
-rw-r--r--src/third_party/gperftools-2.5/SConscript128
-rw-r--r--src/third_party/gperftools-2.5/TODO47
-rw-r--r--src/third_party/gperftools-2.5/build_linux_aarch64/config.h308
-rw-r--r--src/third_party/gperftools-2.5/build_linux_ppc64le/config.h308
-rw-r--r--src/third_party/gperftools-2.5/build_linux_s390x/config.h308
-rw-r--r--src/third_party/gperftools-2.5/build_linux_x86_64/config.h308
-rw-r--r--src/third_party/gperftools-2.5/build_osx_x86_64/config.h308
-rw-r--r--src/third_party/gperftools-2.5/build_solaris_x86_64/config.h308
-rw-r--r--src/third_party/gperftools-2.5/build_windows_x86_64/config.h330
-rw-r--r--src/third_party/gperftools-2.5/src/addressmap-inl.h422
-rw-r--r--src/third_party/gperftools-2.5/src/base/arm_instruction_set_select.h84
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops-internals-arm-generic.h228
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops-internals-arm-v6plus.h330
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops-internals-gcc.h203
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops-internals-linuxppc.h437
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops-internals-macosx.h370
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops-internals-mips.h323
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops-internals-windows.h457
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops-internals-x86.cc112
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops-internals-x86.h391
-rw-r--r--src/third_party/gperftools-2.5/src/base/atomicops.h392
-rw-r--r--src/third_party/gperftools-2.5/src/base/basictypes.h392
-rw-r--r--src/third_party/gperftools-2.5/src/base/commandlineflags.h166
-rw-r--r--src/third_party/gperftools-2.5/src/base/dynamic_annotations.c179
-rw-r--r--src/third_party/gperftools-2.5/src/base/dynamic_annotations.h627
-rw-r--r--src/third_party/gperftools-2.5/src/base/elf_mem_image.cc434
-rw-r--r--src/third_party/gperftools-2.5/src/base/elf_mem_image.h135
-rw-r--r--src/third_party/gperftools-2.5/src/base/elfcore.h401
-rw-r--r--src/third_party/gperftools-2.5/src/base/googleinit.h74
-rw-r--r--src/third_party/gperftools-2.5/src/base/linux_syscall_support.h2755
-rw-r--r--src/third_party/gperftools-2.5/src/base/linuxthreads.cc707
-rw-r--r--src/third_party/gperftools-2.5/src/base/linuxthreads.h54
-rw-r--r--src/third_party/gperftools-2.5/src/base/logging.cc108
-rw-r--r--src/third_party/gperftools-2.5/src/base/logging.h259
-rw-r--r--src/third_party/gperftools-2.5/src/base/low_level_alloc.cc582
-rw-r--r--src/third_party/gperftools-2.5/src/base/low_level_alloc.h120
-rw-r--r--src/third_party/gperftools-2.5/src/base/simple_mutex.h332
-rw-r--r--src/third_party/gperftools-2.5/src/base/spinlock.cc206
-rw-r--r--src/third_party/gperftools-2.5/src/base/spinlock.h149
-rw-r--r--src/third_party/gperftools-2.5/src/base/spinlock_internal.cc102
-rw-r--r--src/third_party/gperftools-2.5/src/base/spinlock_internal.h51
-rw-r--r--src/third_party/gperftools-2.5/src/base/spinlock_linux-inl.h101
-rw-r--r--src/third_party/gperftools-2.5/src/base/spinlock_posix-inl.h63
-rw-r--r--src/third_party/gperftools-2.5/src/base/spinlock_win32-inl.h54
-rw-r--r--src/third_party/gperftools-2.5/src/base/stl_allocator.h98
-rw-r--r--src/third_party/gperftools-2.5/src/base/sysinfo.cc860
-rw-r--r--src/third_party/gperftools-2.5/src/base/sysinfo.h232
-rw-r--r--src/third_party/gperftools-2.5/src/base/thread_annotations.h134
-rw-r--r--src/third_party/gperftools-2.5/src/base/thread_lister.c83
-rw-r--r--src/third_party/gperftools-2.5/src/base/thread_lister.h83
-rw-r--r--src/third_party/gperftools-2.5/src/base/vdso_support.cc143
-rw-r--r--src/third_party/gperftools-2.5/src/base/vdso_support.h132
-rw-r--r--src/third_party/gperftools-2.5/src/central_freelist.cc387
-rw-r--r--src/third_party/gperftools-2.5/src/central_freelist.h217
-rw-r--r--src/third_party/gperftools-2.5/src/common.cc285
-rw-r--r--src/third_party/gperftools-2.5/src/common.h301
-rw-r--r--src/third_party/gperftools-2.5/src/config.h.in307
-rw-r--r--src/third_party/gperftools-2.5/src/config_for_unittests.h65
-rw-r--r--src/third_party/gperftools-2.5/src/debugallocation.cc1490
-rw-r--r--src/third_party/gperftools-2.5/src/emergency_malloc.cc169
-rw-r--r--src/third_party/gperftools-2.5/src/emergency_malloc.h60
-rw-r--r--src/third_party/gperftools-2.5/src/emergency_malloc_for_stacktrace.cc48
-rw-r--r--src/third_party/gperftools-2.5/src/fake_stacktrace_scope.cc39
-rw-r--r--src/third_party/gperftools-2.5/src/getenv_safe.h63
-rw-r--r--src/third_party/gperftools-2.5/src/getpc.h187
-rw-r--r--src/third_party/gperftools-2.5/src/google/heap-checker.h36
-rw-r--r--src/third_party/gperftools-2.5/src/google/heap-profiler.h37
-rw-r--r--src/third_party/gperftools-2.5/src/google/malloc_extension.h36
-rw-r--r--src/third_party/gperftools-2.5/src/google/malloc_extension_c.h37
-rw-r--r--src/third_party/gperftools-2.5/src/google/malloc_hook.h36
-rw-r--r--src/third_party/gperftools-2.5/src/google/malloc_hook_c.h37
-rw-r--r--src/third_party/gperftools-2.5/src/google/profiler.h37
-rw-r--r--src/third_party/gperftools-2.5/src/google/stacktrace.h36
-rw-r--r--src/third_party/gperftools-2.5/src/google/tcmalloc.h37
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/heap-checker.h422
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/heap-profiler.h105
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/malloc_extension.h451
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/malloc_extension_c.h101
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/malloc_hook.h359
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/malloc_hook_c.h173
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/profiler.h169
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/stacktrace.h117
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/t1.sh8
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/tcmalloc.h147
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/tcmalloc.h.in147
-rw-r--r--src/third_party/gperftools-2.5/src/gperftools/tcmalloc.hbak147
-rw-r--r--src/third_party/gperftools-2.5/src/heap-checker-bcad.cc93
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/heap-checker.cc2388
-rw-r--r--src/third_party/gperftools-2.5/src/heap-profile-stats.h78
-rw-r--r--src/third_party/gperftools-2.5/src/heap-profile-table.cc631
-rw-r--r--src/third_party/gperftools-2.5/src/heap-profile-table.h399
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/heap-profiler.cc620
-rw-r--r--src/third_party/gperftools-2.5/src/internal_logging.cc192
-rw-r--r--src/third_party/gperftools-2.5/src/internal_logging.h144
-rw-r--r--src/third_party/gperftools-2.5/src/libc_override.h91
-rw-r--r--src/third_party/gperftools-2.5/src/libc_override_gcc_and_weak.h172
-rw-r--r--src/third_party/gperftools-2.5/src/libc_override_glibc.h146
-rw-r--r--src/third_party/gperftools-2.5/src/libc_override_osx.h281
-rw-r--r--src/third_party/gperftools-2.5/src/libc_override_redefine.h92
-rw-r--r--src/third_party/gperftools-2.5/src/linked_list.h103
-rw-r--r--src/third_party/gperftools-2.5/src/malloc_extension.cc395
-rw-r--r--src/third_party/gperftools-2.5/src/malloc_hook-inl.h249
-rw-r--r--src/third_party/gperftools-2.5/src/malloc_hook.cc703
-rw-r--r--src/third_party/gperftools-2.5/src/malloc_hook_mmap_freebsd.h135
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/malloc_hook_mmap_linux.h252
-rw-r--r--src/third_party/gperftools-2.5/src/maybe_emergency_malloc.h55
-rw-r--r--src/third_party/gperftools-2.5/src/maybe_threads.cc171
-rw-r--r--src/third_party/gperftools-2.5/src/maybe_threads.h61
-rw-r--r--src/third_party/gperftools-2.5/src/memfs_malloc.cc272
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/memory_region_map.cc831
-rw-r--r--src/third_party/gperftools-2.5/src/memory_region_map.h413
-rw-r--r--src/third_party/gperftools-2.5/src/packed-cache-inl.h239
-rw-r--r--src/third_party/gperftools-2.5/src/page_heap.cc697
-rw-r--r--src/third_party/gperftools-2.5/src/page_heap.h328
-rw-r--r--src/third_party/gperftools-2.5/src/page_heap_allocator.h114
-rw-r--r--src/third_party/gperftools-2.5/src/pagemap.h324
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/pprof5590
-rw-r--r--src/third_party/gperftools-2.5/src/profile-handler.cc584
-rw-r--r--src/third_party/gperftools-2.5/src/profile-handler.h142
-rw-r--r--src/third_party/gperftools-2.5/src/profiledata.cc332
-rw-r--r--src/third_party/gperftools-2.5/src/profiledata.h184
-rw-r--r--src/third_party/gperftools-2.5/src/profiler.cc431
-rw-r--r--src/third_party/gperftools-2.5/src/raw_printer.cc72
-rw-r--r--src/third_party/gperftools-2.5/src/raw_printer.h90
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/sampler.cc131
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/sampler.h180
-rw-r--r--src/third_party/gperftools-2.5/src/solaris/libstdc++.la51
-rw-r--r--src/third_party/gperftools-2.5/src/span.cc102
-rw-r--r--src/third_party/gperftools-2.5/src/span.h102
-rw-r--r--src/third_party/gperftools-2.5/src/stack_trace_table.cc160
-rw-r--r--src/third_party/gperftools-2.5/src/stack_trace_table.h92
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace.cc339
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_arm-inl.h148
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_generic-inl.h84
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_impl_setup-inl.h94
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/stacktrace_instrument-inl.h155
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_libgcc-inl.h111
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_libunwind-inl.h150
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_powerpc-darwin-inl.h158
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_powerpc-inl.h176
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_powerpc-linux-inl.h230
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_win32-inl.h107
-rw-r--r--src/third_party/gperftools-2.5/src/stacktrace_x86-inl.h354
-rw-r--r--src/third_party/gperftools-2.5/src/static_vars.cc125
-rw-r--r--src/third_party/gperftools-2.5/src/static_vars.h115
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/symbolize.cc285
-rw-r--r--src/third_party/gperftools-2.5/src/symbolize.h84
-rwxr-xr-xsrc/third_party/gperftools-2.5/src/system-alloc.cc562
-rw-r--r--src/third_party/gperftools-2.5/src/system-alloc.h92
-rw-r--r--src/third_party/gperftools-2.5/src/tcmalloc.cc1915
-rw-r--r--src/third_party/gperftools-2.5/src/tcmalloc.h70
-rw-r--r--src/third_party/gperftools-2.5/src/tcmalloc_guard.h49
-rw-r--r--src/third_party/gperftools-2.5/src/third_party/valgrind.h3924
-rw-r--r--src/third_party/gperftools-2.5/src/thread_cache.cc508
-rw-r--r--src/third_party/gperftools-2.5/src/thread_cache.h480
-rw-r--r--src/third_party/gperftools-2.5/src/windows/TODO86
-rw-r--r--src/third_party/gperftools-2.5/src/windows/addr2line-pdb.c163
-rw-r--r--src/third_party/gperftools-2.5/src/windows/auto_testing_hook.h156
-rw-r--r--src/third_party/gperftools-2.5/src/windows/config.h320
-rw-r--r--src/third_party/gperftools-2.5/src/windows/get_mangled_names.cc65
-rw-r--r--src/third_party/gperftools-2.5/src/windows/gperftools/tcmalloc.h139
-rw-r--r--src/third_party/gperftools-2.5/src/windows/gperftools/tcmalloc.h.in139
-rw-r--r--src/third_party/gperftools-2.5/src/windows/ia32_modrm_map.cc121
-rw-r--r--src/third_party/gperftools-2.5/src/windows/ia32_opcode_map.cc1219
-rw-r--r--src/third_party/gperftools-2.5/src/windows/mingw.h72
-rw-r--r--src/third_party/gperftools-2.5/src/windows/mini_disassembler.cc432
-rw-r--r--src/third_party/gperftools-2.5/src/windows/mini_disassembler.h198
-rw-r--r--src/third_party/gperftools-2.5/src/windows/mini_disassembler_types.h237
-rw-r--r--src/third_party/gperftools-2.5/src/windows/nm-pdb.c273
-rw-r--r--src/third_party/gperftools-2.5/src/windows/override_functions.cc123
-rw-r--r--src/third_party/gperftools-2.5/src/windows/patch_functions.cc1088
-rw-r--r--src/third_party/gperftools-2.5/src/windows/port.cc249
-rw-r--r--src/third_party/gperftools-2.5/src/windows/port.h497
-rw-r--r--src/third_party/gperftools-2.5/src/windows/preamble_patcher.cc736
-rw-r--r--src/third_party/gperftools-2.5/src/windows/preamble_patcher.h620
-rw-r--r--src/third_party/gperftools-2.5/src/windows/preamble_patcher_test.cc368
-rw-r--r--src/third_party/gperftools-2.5/src/windows/preamble_patcher_with_stub.cc302
-rw-r--r--src/third_party/gperftools-2.5/src/windows/shortproc.asm169
-rw-r--r--src/third_party/gperftools-2.5/src/windows/system-alloc.cc204
187 files changed, 2 insertions, 61788 deletions
diff --git a/src/third_party/SConscript b/src/third_party/SConscript
index 67477e1fb57..3330b1ca995 100644
--- a/src/third_party/SConscript
+++ b/src/third_party/SConscript
@@ -33,14 +33,8 @@ thirdPartyEnvironmentModifications = {
}
if not use_system_version_of_library('tcmalloc'):
- # Only gperftools-2.5 is covered here. gperftools-2.7 does something different further
- # down in the file. Its SConscript internally calculates a CPPPATH for its consumers.
- if gperftoolsSuffix == '-2.5':
- thirdPartyEnvironmentModifications['gperftools'] = {
- 'CPPPATH' : ['#/src/third_party/gperftools-2.5/src']
- }
- else:
- thirdPartyEnvironmentModifications['gperftools'] = {}
+ # GPerftools does this slightly differently than the others.
+ thirdPartyEnvironmentModifications['gperftools'] = {}
if not use_system_version_of_library('pcre'):
thirdPartyEnvironmentModifications['pcre'] = {
diff --git a/src/third_party/gperftools-2.5/AUTHORS b/src/third_party/gperftools-2.5/AUTHORS
deleted file mode 100644
index 3995ed4cf57..00000000000
--- a/src/third_party/gperftools-2.5/AUTHORS
+++ /dev/null
@@ -1,2 +0,0 @@
-google-perftools@googlegroups.com
-
diff --git a/src/third_party/gperftools-2.5/COPYING b/src/third_party/gperftools-2.5/COPYING
deleted file mode 100644
index e4956cfd9fd..00000000000
--- a/src/third_party/gperftools-2.5/COPYING
+++ /dev/null
@@ -1,28 +0,0 @@
-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.
diff --git a/src/third_party/gperftools-2.5/ChangeLog b/src/third_party/gperftools-2.5/ChangeLog
deleted file mode 100644
index 4b334beaade..00000000000
--- a/src/third_party/gperftools-2.5/ChangeLog
+++ /dev/null
@@ -1,646 +0,0 @@
-Fri Feb 03 15:40:45 2012 Google Inc. <google-perftools@googlegroups.com>
-
- * gperftools: version 2.0
- * Renamed the project from google-perftools to gperftools (csilvers)
- * Renamed the .deb/.rpm packagse from google-perftools to gperftools too
- * Renamed include directory from google/ to gperftools/ (csilvers)
- * Changed the 'official' perftools email in setup.py/etc
- * Renamed google-perftools.sln to gperftools.sln
- * PORTING: Removed bash-isms & grep -q in heap-checker-death_unittest.sh
- * Changed copyright text to reflect Google's relinquished ownership
-
-Tue Jan 31 10:43:50 2012 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.10 release
- * PORTING: Support for patching assembly on win x86_64! (scott.fr...)
- * PORTING: Work around atexit-execution-order bug on freebsd (csilvers)
- * PORTING: Patch _calloc_crt for windows (roger orr)
- * PORTING: Add C++11 compatibility method for stl allocator (jdennett)
- * PORTING: use MADV_FREE, not MADV_DONTNEED, on freebsd (csilvers)
- * PORTING: Don't use SYS_open when not supported on solaris (csilvers)
- * PORTING: Do not assume uname() returns 0 on success (csilvers)
- * LSS: Improved ARM support in linux-syscall-support (dougkwan)
- * LSS: Get rid of unused syscalls in linux-syscall-support (csilvers)
- * LSS: Fix broken mmap wrapping for ppc (markus)
- * LSS: Emit .cfi_adjust_cfa_offset when appropriate (ppluzhnikov)
- * LSS: Be more accurate in register use in __asm__ (markus)
- * LSS: Fix __asm__ calls to compile under clang (chandlerc)
- * LSS: Fix ARM inline assembly bug around r7 and swi (lcwu)
- * No longer log when an allocator fails (csilvers)
- * void* -> const void* for MallocExtension methods (llib)
- * Improve HEAP_PROFILE_MMAP and fix bugs with it (dmikurube)
- * Replace int-based abs with more correct fabs in a test (pmurin)
-
-Thu Dec 22 16:22:45 2011 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.9 release
- * Lightweight check for double-frees (blount)
- * BUGFIX: Fix pprof to exit properly if run with no args (dagitses)
- * Suggest ASan as a way to diagnose buggy code (ppluzhnikov)
- * Get rid of unused CACHELINE_SIZE (csilvers)
- * Replace atexit() calls with global dtors; helps freebsd (csilvers)
- * Disable heap-checker under AddressSanitizer (kcc)
- * Fix bug in powerpc stacktracing (ppluzhnikov)
- * PERF: Use exponential backoff waiting for spinlocks (m3b)
- * Fix 64-bit nm on 32-bit binaries in pprof (csilvers)
- * Add ProfileHandlerDisallowForever (rsc)
- * BUGFIX: Shell escape when forking in pprof (csilvers)
- * No longer combine overloaded functions in pprof (csilvers)
- * Fix address-normalizing bug in pprof (csilvers)
- * More consistently call abort() instead of exit() on failure (csilvers)
- * Allow NoGlobalLeaks to be safely called more than once (csilvers)
- * PORTING/BUGFIX: Fix ARM cycleclock to use volatile asm (dougkwan)
- * PORTING: 64-bit atomic ops for ARMv7 (dougkwan)
- * PORTING: Implement stacktrace for ARM (dougkwan)
- * PORTING: Fix malloc_hook_mmap_linux for ARM (dougkwan)
- * PORTING: Update linux_syscall_support.h for ARM/etc (evannier, sanek)
- * PORTING: Fix freebsd to work on x86_64 (chapp...@gmail.com)
- * PORTING: Added additional SYS_mmap fixes for FreeBSD (chappedm)
- * PORTING: Allow us to compile on OS X 10.6 and run on 10.5 (raltherr)
- * PORTING: Check for mingw compilers that *do* define timespec
- * PORTING: Add "support" for MIPS cycletimer
- * PORTING: Fix fallback cycle-timer to work with Now (dougkwan)
- * PERF: Move stack trace collecting out of the mutex (taylorc)
- * PERF: Get the deallocation stack trace outside the mutex (sean)
- * Make PageHeap dynamically allocated for leak checks (maxim)
- * BUGFIX: Fix probing of nm -f behavior in pprof (dpeng)
- * BUGFIX: Fix a race with the CentralFreeList lock before main (sanjay)
- * Support /pprof/censusprofile url arguments (rajatjain)
- * Change IgnoreObject to return its argument (nlewycky)
- * Update malloc-hook files to support more CPUs
- * BUGFIX: write our own strstr to avoid libc problems (csilvers)
- * Use simple callgrind compression facility in pprof
- * Print an error message when we can't run pprof to symbolize (csilvers)
- * Die in configure when g++ is't installed (csilvers)
- * DOC: Beef up the documentation a bit about using libunwind (csilvers)
-
-Fri Aug 26 13:29:25 2011 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.8.3 release
- * Added back the 'pthreads unsafe early' #define, needed for FreeBSD
-
-Thu Aug 11 15:01:47 2011 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.8.2 release
- * Fixed calculation of patchlevel, 'make check' should all pass again
-
-Tue Jul 26 20:57:51 2011 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.8.1 release
- * Added an #include to fix compile breakage on latest gcc's
- * Removed an extra , in the configure.ac script
-
-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
- * Reduce page map key size under x86_64 by 4.4MB (rus)
- * Remove a flaky malloc-extension test (fdabek)
- * Improve the performance of PageHeap::New (ond..., csilvers)
- * Improve sampling_test with no-inline additions/etc (fdabek)
- * 16-byte align debug allocs (jyasskin)
- * Change FillProcSelfMaps to detect out-of-buffer-space (csilvers)
- * Document the need for sampling to use GetHeapSample (csilvers)
- * Try to read TSC frequency from tsc_freq_khs (adurbin)
- * Do better at figuring out if tests are running under gdb (ppluzhnikov)
- * Improve spinlock contention performance (ruemmler)
- * Better internal-function list for pprof's /contention (ruemmler)
- * Speed up GoogleOnce (m3b)
- * Limit number of incoming/outgoing edges in pprof (sanjay)
- * Add pprof --evince to go along with --gv (csilvers)
- * Document the various ways to get heap-profiling information (csilvers)
- * Separate out synchronization profiling routines (ruemmler)
- * Improve malloc-stats output to be more understandable (csilvers)
- * Add support for census profiler in pporf (nabeelmian)
- * Document how pprof's /symbol must support GET requests (csilvers)
- * Improve acx_pthread.m4 (ssuomi, liujisi)
- * Speed up pprof's ExtractSymbols (csilvers)
- * Ignore some known-leaky (java) libraries in the heap checker (davidyu)
- * Make kHideMask use all 64 bits in tests (ppluzhnikov)
- * Clean up pprof input-file handling (csilvers)
- * BUGFIX: Don't crash if __environ is NULL (csilvers)
- * BUGFIX: Fix totally broken debugallocation tests (csilvers)
- * BUGFIX: Fix up fake_VDSO handling for unittest (ppluzhnikov)
- * BUGFIX: Suppress all large allocs when report threshold is 0 (lexie)
- * BUGFIX: mmap2 on i386 takes an off_t, not off64_t (csilvers)
- * PORTING: Add missing PERFTOOLS_DLL_DECL (csilvers)
- * PORTING: Add stddef.h to make newer gcc's happy (csilvers)
- * PORTING: Document some tricks for working under OS X (csilvers)
- * PORTING: Don't try to check valgrind for windows (csilvers)
- * PORTING: Make array-size a var to compile under clang (chandlerc)
- * PORTING: No longer hook _aligned_malloc and _aligned_free (csilvers)
- * PORTING: Quiet some gcc warnings (csilvers)
- * PORTING: Replace %PRIxPTR with %p to be more portable (csilvers)
- * PORTING: Support systems that capitalize /proc weirdly (sanek)
- * PORTING: Treat arm3 the same as arm5t in cycletimer (csilvers)
- * PORTING: Update windows logging to not allocate memory (csilvers)
- * PORTING: avoid double-patching newer windows DLLs (roger.orr)
- * PORTING: get dynamic_annotations.c to work on windows (csilvers)
- * Add pkg-config .pc files for the 5 libraries we produce (csilvers)
- * Added proper libtool versioning, so this lib will be 0.1.0 (csilvers)
- * Moved from autoconf 2.64 to 2.65
-
-Thu Aug 5 12:48:03 PDT 2010 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.6 release
- * Add tc_malloc_usable_size for compatibility with glibc (csilvers)
- * Override malloc_usable_size with tc_malloc_usable_size (csilvers)
- * Default to no automatic heap sampling in tcmalloc (csilvers)
- * Add -DTCMALLOC_LARGE_PAGES, a possibly faster tcmalloc (rus)
- * Make some functions extern "C" to avoid false ODR warnings (jyasskin)
- * pprof: Add SVG-based output (rsc)
- * pprof: Extend pprof --tools to allow per-tool configs (csilvers)
- * pprof: Improve support of 64-bit and big-endian profiles (csilvers)
- * pprof: Add interactive callgrind suport (weidenri...)
- * pprof: Improve address->function mapping a bit (dpeng)
- * Better detection of when we're running under valgrind (csilvers)
- * Better CPU-speed detection under valgrind (saito)
- * Use, and recommend, -fno-builtin-malloc when compiling (csilvers)
- * Avoid false-sharing of memory between caches (bmaurer)
- * BUGFIX: Fix heap sampling to use correct alloc size (bmauer)
- * BUGFIX: Avoid gcc 4.0.x bug by making hook-clearing atomic (csilvers)
- * BUGFIX: Avoid gcc 4.5.x optimization bug (csilvers)
- * BUGFIX: Work around deps-determining bug in libtool 1.5.26 (csilvers)
- * BUGFIX: Fixed test to use HAVE_PTHREAD, not HAVE_PTHREADS (csilvers)
- * BUGFIX: Fix tls callback behavior on windows when using wpo (wtc)
- * BUGFIX: properly align allocation sizes on Windows (antonm)
- * BUGFIX: Fix prototypes for tcmalloc/debugalloc wrt throw() (csilvers)
- * DOC: Updated heap-checker doc to match reality better (fischman)
- * DOC: Document ProfilerFlush, ProfilerStartWithOptions (csilvers)
- * DOC: Update docs for heap-profiler functions (csilvers)
- * DOC: Clean up documentation around tcmalloc.slack_bytes (fikes)
- * DOC: Renamed README.windows to README_windows.txt (csilvers)
- * DOC: Update the NEWS file to be non-empty (csilvers)
- * PORTING: Fix windows addr2line and nm with proper rc code (csilvers)
- * PORTING: Add CycleClock and atomicops support for arm 5 (sanek)
- * PORTING: Improve PC finding on cygwin and redhat 7 (csilvers)
- * PORTING: speed up function-patching under windows (csilvers)
-
-Tue Jan 19 14:46:12 2010 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.5 release
- * Add tc_set_new_mode (willchan)
- * Make memalign functions + realloc respect tc_set_new_mode (willchan)
- * Add ReleaseToSystem(num_bytes) (kash)
- * Handle zero-length symbols a bit better in pprof (csilvers)
- * Prefer __environ to /proc/self/environ in cpu profiler (csilvers)
- * Add HEAP_CHECK_MAX_LEAKS flag to control #leaks to report (glider)
- * Add two new numeric pageheap properties to MallocExtension (fikes)
- * Print alloc size when mmap fails (hakon)
- * Add ITIMER_REAL support to cpu profiler (csilvers, nabeelmian)
- * Speed up symbolizer in heap-checker reporting (glider)
- * Speed up futexes with FUTEX_PRIVATE_FLAG (m3b)
- * Speed up tcmalloc but doing better span coalescing (sanjay)
- * Better support for different wget's and addr2maps in pprof (csilvres)
- * Implement a nothrow version of delete and delete[] (csilvers)
- * BUGFIX: fix a race on module_libcs[i] in windows patching (csilvers)
- * BUGFIX: Fix debugallocation to call cpp_alloc for new (willchan)
- * BUGFIX: A simple bugfix for --raw mode (mrabkin)
- * BUGFIX: Fix C shims to actually be valid C (csilvers)
- * BUGFIX: Fix recursively-unmapped-region accounting (ppluzhnikov)
- * BUGFIX: better distinguish real and fake vdso (ppluzhnikov)
- * WINDOWS: replace debugmodule with more reliable psai (andrey)
- * PORTING: Add .bundle as another shared library extension (csilvers)
- * PORTING: Fixed a typo bug in the ocnfigure PRIxx m4 macro (csilvers)
- * PORTING: Augment sysinfo to work on 64-bit OS X (csilvers)
- * PORTING: Use sys/ucontext.h to fix compiing on OS X 10.6 (csilvers)
- * PORTING: Fix sysinfo libname reporting for solaris x86 (jeffrey)
- * PORTING: Use libunwind for i386 when using --omitfp (ppluzhnikov)
-
-Thu Sep 10 13:51:15 2009 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.4 release
- * Add debugallocation library, to catch memory leaks, stomping, etc
- * Add --raw mode to allow for delayed processing of pprof files
- * Use less memory when reading CPU profiles
- * New environment variables to control kernel-allocs (sbrk, memfs, etc)
- * Add MarkThreadBusy(): performance improvement
- * Remove static thread-cache-size code; all is dynamic now
- * Add new HiddenPointer class to heap checker
- * BUGFIX: pvalloc(0) allocates now (found by new debugalloc library)
- * BUGFIX: valloc test (not implementation) no longer overruns memory
- * BUGFIX: GetHeapProfile no longer deadlocks
- * BUGFIX: Support unmapping memory regions before main
- * BUGFIX: Fix some malloc-stats formatting
- * BUGFIX: Don't crash as often when freeing libc-allocated memory
- * BUGFIX: Deal better with incorrect PPROF_PATH when symbolizing
- * BUGFIX: weaken new/delete/etc in addition to malloc/free/etc
- * BUGFIX: Fix return value of GetAllocatedSize
- * PORTING: Fix mmap-#define problem on some 64-bit systems
- * PORTING: Call ranlib again (some OS X versions need it)
- * PORTING: Fix a leak when building with LLVM
- * PORTING: Remove some unneeded bash-ishs from testing scripts
- * WINDOWS: Support library unloading as well as loading
- * WINDOWS/BUGFIX: Set page to 'xrw' instead of 'rw' when patching
-
-Tue Jun 9 18:19:06 2009 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.3 release
- * Provide our own name for memory functions: tc_malloc, etc (csilvers)
- * Weaken memory-alloc functions so user can override them (csilvers)
- * Remove meaningless delete(nothrow) and delete[](nothrow) (csilvers)
- * BUILD: replace clever libtcmalloc/profiler.a with a new .a (csilvers)
- * PORTING: improve windows port by using google spinlocks (csilvers)
- * PORTING: Fix RedHat 9 memory allocation in heapchecker (csilvers)
- * PORTING: Rename OS_WINDOWS macro to PLATFORM_WINDOWS (mbelshe)
- * PORTING/BUGFIX: Make sure we don't clobber GetLastError (mbelshe)
- * BUGFIX: get rid of useless data for callgrind (weidenrinde)
- * BUGFIX: Modify windows patching to deadlock sometimes (csilvers)
- * BUGFIX: an improved fix for hook handling during fork (csilvers)
- * BUGFIX: revamp profiler_unittest.sh, which was very broken (csilvers)
-
-Fri Apr 17 16:40:48 2009 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.2 release
- * Allow large_alloc_threshold=0 to turn it off entirely (csilvers)
- * Die more helpfully when out of memory for internal data (csilvers)
- * Refactor profile-data gathering, add a new unittest (cgd, nabeelmian)
- * BUGFIX: fix rounding errors with static thread-size caches (addi)
- * BUGFIX: disable hooks better when forking in leak-checker (csilvers)
- * BUGFIX: fix realloc of crt pointers on windows (csilvers)
- * BUGFIX: do a better job of finding binaries in .sh tests (csilvers)
- * WINDOWS: allow overriding malloc/etc instead of patching (mbelshe)
- * PORTING: fix compilation error in a ppc-specific file (csilvers)
- * PORTING: deal with quirks in cygwin's /proc/self/maps (csilvers)
- * PORTING: use 'A' version of functions for ascii input (mbelshe)
- * PORTING: generate .so's on cygwin and mingw (ajenjo)
- * PORTING: disable profiler methods on cygwin (jperkins)
- * Updated autoconf version to 2.61 and libtool version to 1.5.26
-
-Wed Mar 11 11:25:34 2009 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.1 release
- * Dynamically resize thread caches -- nice perf. improvement (kash)
- * Add VDSO support to give better stacktraces in linux (ppluzhnikov)
- * Improve heap-profiling sampling algorithm (ford)
- * Rewrite leak-checking code: should be faster and more robust (sanjay)
- * Use ps2 instead of ps for dot: better page cropping for gv (csilvers)
- * Disable malloc-failure warning messages by default (csilvers)
- * Update config/Makefile to disable tests on a per-OS basis (csilvers)
- * PORTING: Get perftools compiling under MSVC 7.1 again (csilvers)
- * PORTING: Get perftools compiling under cygwin again (csilvers)
- * PORTING: automatically set library flags for solaris x86 (csilvers)
- * Add TCMALLOC_SKIP_SBRK to mirror TCMALLOC_SKIP_MMAP (csilvers)
- * Add --enable flags to allow selective building (csilvers)
- * Put addr2line-pdb and nm-pdb in proper output directory (csilvers)
- * Remove deprecated DisableChecksIn (sanjay)
- * DOCUMENTATION: Document most MallocExtension routines (csilvers)
-
-Tue Jan 6 13:58:56 2009 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.0 release
- * Exactly the same as 1.0rc2
-
-Sun Dec 14 17:10:35 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.0rc2 release
- * Fix compile error on 64-bit systems (casting ptr to int) (csilvers)
-
-Thu Dec 11 16:01:32 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 1.0rc1 release
- * Replace API for selectively disabling heap-checker in code (sanjay)
- * Add a pre-mmap hook (daven, adlr)
- * Add MallocExtension interface to set memory-releasing rate (fikes)
- * Augment pprof to allow any string ending in /pprof/profile (csilvers)
- * PORTING: Rewrite -- and fix -- malloc patching for windows (dvitek)
- * PORTING: Add nm-pdb and addr2line-pdb for use by pprof (dvitek)
- * PORTING: Improve cygwin and mingw support (jperkins, csilvers)
- * PORTING: Fix pprof for mac os x, other pprof improvements (csilvers)
- * PORTING: Fix some PPC bugs in our locking code (anton.blanchard)
- * A new unittest, smapling_test, to verify tcmalloc-profiles (csilvers)
- * Turn off TLS for gcc < 4.1.2, due to a TLS + -fPIC bug (csilvers)
- * Prefer __builtin_frame_address to assembly for stacktraces (nlewycky)
- * Separate tcmalloc.cc out into multiple files -- finally! (kash)
- * Make our locking code work with -fPIC on 32-bit x86 (aruns)
- * Fix an initialization-ordering bug for tcmalloc/profiling (csilvers)
- * Use "initial exec" model of TLS to speed up tcmalloc (csilvers)
- * Enforce 16-byte alignment for tcmalloc, for SSE (sanjay)
-
-Tue Sep 23 08:56:31 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.99.2 release
- * COMPILE FIX: add #include needed for FreeBSD and OS X (csilvers)
-
-Sat Sep 20 09:37:18 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.99.1 release
- * BUG FIX: look for nm, etc in /usr/bin, not /usr/crosstool (csilvers)
-
-Thu Sep 18 16:00:27 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.99 release
- * Add IsHeapProfileRunning (csilvers)
- * Add C shims for some of the C++ header files (csilvers)
- * Fix heap profile file clean-up logic (maxim)
- * Rename linuxthreads.c to .cc for better compiler support (csilvers)
- * Add source info to disassembly in pprof (sanjay)
- * Use open instead of fopen to avoid memory alloc (csilvers)
- * Disable malloc extensions when running under valgrind (kcc)
- * BUG FIX: Fix out-of-bound error by reordering a check (larryz)
- * Add Options struct to ProfileData (cgd)
- * Correct PC-handling of --base in pprof (csilvers)
- * Handle 1 function occurring twice in an image (sanjay)
- * Improve stack-data cleaning (maxim)
- * Use 'struct Foo' to make header C compatible (csilvers)
- * Add 'total' line to pprof --text (csilvers)
- * Pre-allocate buffer for heap-profiler to avoid OOM errors (csilvers)
- * Allow a few more env-settings to control tcmalloc (csilvers)
- * Document some of the issues involving thread-local storage (csilvers)
- * BUG FIX: Define strtoll and friends for windows (csilvers)
-
-Mon Jun 9 16:47:03 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.98 release
- * Add ProfilerStartWithOptions() (cgd)
- * Change tcmalloc_minimal to not do any stack-tracing at all (csilvers)
- * Prefer mmap to sbrk for 64-buit debug mode (sanjay)
- * Fix accounting for some tcmalloc stats (sanjay)
- * Use setrlimit() to keep unittests from killing the machine (odo)
- * Fix a bug when sbrk-ing near address 4G (csilvers)
- * Make MallocHook thread-safe (jyasskin)
- * Fix windows build for MemoryBarrier (jyasskin)
- * Fix CPU-profiler docs to mention correct libs (csilvers)
- * Fix for GetHeapProfile() when heap-profiling is off (maxim)
- * Avoid realloc resizing ping-pongs using hysteresis (csilvers)
- * Add --callgrind output support to pprof (klimek)
- * Fix profiler.h and heap-profiler.h to be C-compatible (csilvers)
- * Break malloc_hook.h into two parts to reduce dependencies (csilvers)
- * Better handle systems that don't implement mmap (csilvers)
- * PORTING: disable system_alloc_unittest for msvc (csilvers)
- * PORTING: Makefile tweaks to build better on cygwin (csilvers)
-
-Mon Apr 21 15:20:52 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.97 release
- * Refactor GetHeapProfile to avoid using malloc (maxim)
- * Fix heap-checker and heap-profiler hook interactions (maxim)
- * Fix a data race in MemoryRegionMap::Lock (jyasskin)
- * Improve thread-safety of leak checker (maxim)
- * Fix mmap profile to no longer deadlock (maxim)
- * Fix rpm to have devel package depend on non-devel (csilvers)
- * PORTING: Fix clock-speed detection for Mac OS X (csilvers)
-
-Tue Mar 18 14:30:44 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.96 release
- * major atomicops rewrite; fixed atomic ops code for linux/ppc (vchen)
- * nix the stacktrace library; now build structure is simpler (csilvers)
- * Speed up heap-checker, and reduce extraneous logging (maxim)
- * Improve itimer code for NPTL case (cgd)
- * Add source code annotations for use by valgrind, etc (kcc)
- * PORTING: Fix high resolution timers for Mac OS X (adlr)
-
-Tue Feb 19 12:01:31 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.95.1 release (bugfix release)
- * x86_64 compile-fix: nix pread64 and pwrite64 (csilvers)
- * more heap-checker debug logging (maxim)
- * minor improvement to x86_64 CycleClock (gpike)
-
-Tue Feb 12 12:28:32 2008 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.95 release
- * Better -- not perfect -- support for linux-ppc (csilvers)
- * Fix race condition in libunwind stacktrace (aruns)
- * Speed up x86 spinlock locking (m3b)
- * Improve heap-checker performance (maxim)
- * Heap checker traverses more ptrs inside heap-alloced objects (maxim)
- * Remove deprecated ProfilerThreadState function (cgd)
- * Update libunwind documentation for statically linked binaries (aruns)
-
-Mon Dec 3 23:51:54 2007 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.94.1 release (bugfix release)
- * Fix missing #includes for x86_64 compile using libunwind (csilvers)
-
-Thu Nov 29 07:59:43 2007 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.94 release
- * PORTING: MinGW/Msys support -- runs same code as MSVC does (csilvers)
- * PORTING: Add NumCPUs support for Mac OS X (csilvers)
- * Work around a sscanf bug in glibc(?) (waldemar)
- * Fix Windows MSVC bug triggered by thread deletion (csilvers)
- * Fix bug that triggers in MSVC /O2: missing volatile (gpike)
- * March-of-time support: quiet warnings/errors for gcc 4.2, OS X 10.5
- * Modify pprof so it works without nm: useful for windows (csilvers)
- * pprof: Support filtering for CPU profiles (cgd)
- * Bugfix: have realloc report to hooks in all situations (maxim)
- * Speed improvement: replace slow memcpy with std::copy (soren)
- * Speed: better iterator efficiency in RecordRegionRemoval (soren)
- * Speed: minor speed improvements via better bitfield alignment (gpike)
- * Documentation: add documentation of binary profile output (cgd)
-
-Fri Aug 17 12:32:56 2007 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.93 release
- * PORTING: everything compiles on Solaris, OS X, FreeBSD (see INSTALL)
- * PORTING: cpu-profiler works on most platforms (much better GetPC())
- * PORTING: heap-profiler works on most platforms
- * PORTING: improved windows support, including release builds
- * No longer build or run ptmalloc tests by default
- * Add support for using memfs filesystem to allocate memory in linux
- * WINDOWS: give debug library and release library different names
-
-Tue Jul 17 22:26:27 2007 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.92 release
- * PERFORMANCE: use a packed cache to speed up tcmalloc
- * PORTING: preliminary windows support! (see README.windows)
- * PORTING: better support for solaris, OS X, FreeBSD (see INSTALL)
- * Envvar support for running the heap-checker under gdb
- * Add weak declarations to maybe_threads to fix no-pthreads compile bugs
- * Some 64bit fixes, especially with pprof
- * Better heap-checker support for some low-level allocations
- * Fix bug where heap-profiles would sometimes get truncated
- * New documentation about how to handle common heap leak situations
- * Use computed includes for hash_map/set: easier config
- * Added all used .m4 templates to the distribution
-
-Wed Apr 18 16:43:55 2007 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.91 release
- * Brown-paper-bag bugfix: compilation error on some x86-64 machines
-
-Fri Apr 13 14:50:51 2007 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.90 release
- * (As the version-number jump hints, this is a major new release:
- almost every piece of functionality was rewritten. I can't do
- justice to all the changes, but will concentrate on highlights.)
- *** USER-VISIBLE CHANGES:
- * Ability to "release" unused memory added to tcmalloc
- * Exposed more tweaking knobs via environment variables (see docs)
- * pprof tries harder to map addresses to functions
- * tcmalloc_minimal compiles and runs on FreeBSD 6.0 and Solaris 10
- *** INTERNAL CHANGES:
- * Much better 64-bit support
- * Better multiple-processor support (e.g. multicore contention tweaks)
- * Support for recent kernel ABI changes (e.g. new arg to mremap)
- * Addition of spinlocks to tcmalloc to reduce contention cost
- * Speed up tcmalloc by using __thread on systems that support TLS
- * Total redesign of heap-checker to improve liveness checking
- * More portable stack-frame analysis -- no more hard-coded constants!
- * Disentangled heap-profiler code and heap-checker code
- * Several new unittests to test, e.g., thread-contention costs
- * Lots of small (but important!) bug fixes: e.g., fixing GetPC on amd64
- *** KNOWN PROBLEMS:
- * CPU-profiling may crash on x86_64 (64-bit) systems. See the README
- * Profiling/heap-checking may deadlock on x86_64 systems. See README
-
-Wed Jun 14 15:11:14 2006 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.8 release
- * Experimental support for remote profiling added to pprof (many)
- * Fixed race condition in ProfileData::FlushTable (etune)
- * Better support for weird /proc maps (maxim, mec)
- * Fix heap-checker interaction with gdb (markus)
- * Better 64-bit support in pprof (aruns)
- * Reduce scavenging cost in tcmalloc by capping NumMoveSize (sanjay)
- * Cast syscall(SYS_mmap); works on more 64-bit systems now (menage)
- * Document the text output of pprof! (csilvers)
- * Better compiler support for no-THREADS and for old compilers (csilvers)
- * Make libunwind the default stack unwinder for x86-64 (aruns)
- * Somehow the COPYING file got erased. Regenerate it (csilvers)
-
-Thu Apr 13 20:59:09 2006 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.7 release
- * Major rewrite of thread introspection for new kernels (markus)
- * Major rewrite of heap-checker to use new thread tools (maxim)
- * Add proper support for following data in thread registers (maxim)
- * Syscall support for older kernels, including _syscall6 (markus)
- * Support PIC mode (markus, mbland, iant)
- * Better support for running in non-threaded contexts (csilvers)
-
-Fri Jan 27 14:04:27 2006 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.6 release
- * More sophisticated stacktrace usage, possibly using libunwind (aruns)
- * Update pprof to handle 64-bit profiles (dehnert)
- * Fix GetStackTrace to correctly return top stackframe (sanjay)
- * Add ANSI compliance for new and new[], including new_handler (jkearney)
- * More accuracy by reading ELF files directly rather than objdump (mec)
- * Add readline support for pprof (addi)
- * Add #includes for PPC (csilvers)
- * New PC-detection routine for ibook powerpc (asbestoshead)
- * Vastly improved tcmalloc unittest (csilvers)
- * Move documentation from /usr/doc to /usr/share/doc
-
-Mon Nov 14 17:28:59 2005 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.5 release
- * Add va_start/va_end calls around vsnprintf() (csilvers)
- * Write our own __syscall_return(), since it's not defined
- consistently on all 64-bit linux distros (markus)
-
-Wed Oct 26 15:19:16 2005 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.4 release
- * Decrease fragmentation in tcmalloc (lefevere)
- * Support for ARM in some of the thread-specific code (markus)
- * Turn off heap-checker for statically-linked binaries, which
- cause error leak reports now (etune)
- * Many pprof improvements, including a command-line interface (jeff)
- * CPU profiling now automatically affects all threads in linux 2.6.
- (Kernel bugs break CPU profiling and threads in linux 2.4 a bit.)
- ProfilerEnable() and ProfilerDisable() are deprecated. (sanjay)
- * tcmalloc now correctly intercepts memalign (m3b, maxim)
- * Syntax fix: added missing va_end()s. Helps non-gcc compiling (etune)
- * Fixed a few coredumper bugs: race condition after PTRACE_DETACH,
- ignore non-aligned stackframe pointers (markus, menage)
- * 64-bit cleanup, especially for spinlock code (etune) and mmap (sanjay)
- * Better support for finding threads in linux (markus)
- * tcmalloc now tracks those stack traces that allocate memory (sanjay)
- * Work around a weird setspecific problem (sanjay)
- * Fix tcmalloc overflow problems when an alloc is close to 2G/4G (sanjay)
-
-Fri Jun 24 18:02:26 2005 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.3 release
- * Add missing errno include for one of the unittests (csilvers)
- * Reduce tcmalloc startup memory from 5M to 256K (sanjay)
- * Add support for mallopt() and mallinfo (sanjay)
- * Improve stacktrace's performance on some 64-bit systems (etune)
- * Improve the stacktrace unittest (etune)
-
-Tue May 31 08:14:38 2005 Google Inc. <opensource@google.com>
-
- * google-perftools: version 0.2 release
- * Use mmap2() instead of mmap(), to map more memory (menage)
- * Do correct pthread-local checking in heap-checker! (maxim)
- * Avoid overflow on 64-bit machines in pprof (sanjay)
- * Add a few more GetPC() functions, including for AMD (csilvers)
- * Better method for overriding pthread functions (menage)
- * (Hacky) fix to avoid overwriting profile files after fork() (csilvers)
- * Crashing bugfix involving dumping heaps on small-stack threads (tudor)
- * Allow library versions with letters at the end (csilvers)
- * Config fixes for systems that don't define PATH_MAX (csilvers)
- * Confix fixes so we no longer need config.h after install (csilvers)
- * Fix to pprof to correctly read very big cpu profiles (csilvers)
- * Fix to pprof to deal with new commandline flags in modern gv's
- * Better error reporting when we can't access /proc/maps (etune)
- * Get rid of the libc-preallocate code (which could crash on some
- systems); no longer needed with local-threads fix (csilvers)
-
-Tue Feb 8 09:57:17 2005 Google Inc. <opensource@google.com>
-
- * google-perftools: initial release:
- The google-perftools package contains some utilities to improve
- and analyze the performance of C++ programs. This includes an
- optimized thread-caching malloc() and cpu and heap profiling
- utilities.
diff --git a/src/third_party/gperftools-2.5/INSTALL b/src/third_party/gperftools-2.5/INSTALL
deleted file mode 100644
index f9a6a117289..00000000000
--- a/src/third_party/gperftools-2.5/INSTALL
+++ /dev/null
@@ -1,563 +0,0 @@
-Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
-Foundation, Inc.
-
- This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-
-Perftools-Specific Install Notes
-================================
-
-*** Building from source repository
-
-As of 2.1 gperftools does not have configure and other autotools
-products checked into it's source repository. This is common practice
-for projects using autotools.
-
-NOTE: Source releases (.tar.gz that you download from
-code.google.com/p/gperftools) still have all required files just as
-before. Nothing has changed w.r.t. building from .tar.gz releases.
-
-But, in order to build gperftools checked out from subversion
-repository you need to have autoconf, automake and libtool
-installed. And before running ./configure you have to generate it (and
-a bunch of other files) by running ./autogen.sh script. That script
-will take care of calling correct autotools programs in correct order.
-
-If you're maintainer then it's business as usual too. Just run make
-dist (or, preferably, make distcheck) and it'll produce .tar.gz or
-.tar.bz2 with all autotools magic already included. So that users can
-build our software without having autotools.
-
-
-*** NOTE FOR 64-BIT LINUX SYSTEMS
-
-The glibc built-in stack-unwinder on 64-bit systems has some problems
-with the perftools libraries. (In particular, the cpu/heap profiler
-may be in the middle of malloc, holding some malloc-related locks when
-they invoke the stack unwinder. The built-in stack unwinder may call
-malloc recursively, which may require the thread to acquire a lock it
-already holds: deadlock.)
-
-For that reason, if you use a 64-bit system, we strongly recommend you
-install libunwind before trying to configure or install gperftools.
-libunwind can be found at
-
- http://download.savannah.gnu.org/releases/libunwind/libunwind-0.99-beta.tar.gz
-
-Even if you already have libunwind installed, you should check the
-version. Versions older than this will not work properly; too-new
-versions introduce new code that does not work well with perftools
-(because libunwind can call malloc, which will lead to deadlock).
-
-There have been reports of crashes with libunwind 0.99 (see
-http://code.google.com/p/gperftools/issues/detail?id=374).
-Alternately, you can use a more recent libunwind (e.g. 1.0.1) at the
-cost of adding a bit of boilerplate to your code. For details, see
-http://groups.google.com/group/google-perftools/msg/2686d9f24ac4365f
-
- CAUTION: if you install libunwind from the url above, be aware that
- you may have trouble if you try to statically link your binary with
- perftools: that is, if you link with 'gcc -static -lgcc_eh ...'.
- This is because both libunwind and libgcc implement the same C++
- exception handling APIs, but they implement them differently on
- some platforms. This is not likely to be a problem on ia64, but
- may be on x86-64.
-
- Also, if you link binaries statically, make sure that you add
- -Wl,--eh-frame-hdr to your linker options. This is required so that
- libunwind can find the information generated by the compiler
- required for stack unwinding.
-
- Using -static is rare, though, so unless you know this will affect
- you it probably won't.
-
-If you cannot or do not wish to install libunwind, you can still try
-to use the built-in stack unwinder. The built-in stack unwinder
-requires that your application, the tcmalloc library, and system
-libraries like libc, all be compiled with a frame pointer. This is
-*not* the default for x86-64.
-
-If you are on x86-64 system, know that you have a set of system
-libraries with frame-pointers enabled, and compile all your
-applications with -fno-omit-frame-pointer, then you can enable the
-built-in perftools stack unwinder by passing the
---enable-frame-pointers flag to configure.
-
-Even with the use of libunwind, there are still known problems with
-stack unwinding on 64-bit systems, particularly x86-64. See the
-"64-BIT ISSUES" section in README.
-
-If you encounter problems, try compiling perftools with './configure
---enable-frame-pointers'. Note you will need to compile your
-application with frame pointers (via 'gcc -fno-omit-frame-pointer
-...') in this case.
-
-
-*** TCMALLOC LARGE PAGES: TRADING TIME FOR SPACE
-
-You can set a compiler directive that makes tcmalloc faster, at the
-cost of using more space (due to internal fragmentation).
-
-Internally, tcmalloc divides its memory into "pages." The default
-page size is chosen to minimize memory use by reducing fragmentation.
-The cost is that keeping track of these pages can cost tcmalloc time.
-We've added a new flag to tcmalloc that enables a larger page size.
-In general, this will increase the memory needs of applications using
-tcmalloc. However, in many cases it will speed up the applications
-as well, particularly if they allocate and free a lot of memory. We've
-seen average speedups of 3-5% on Google applications.
-
-To build libtcmalloc with large pages you need to use the
---with-tcmalloc-pagesize=ARG configure flag, e.g.:
-
- ./configure <other flags> --with-tcmalloc-pagesize=32
-
-The ARG argument can be 8, 32 or 64 which sets the internal page size to
-8K, 32K and 64K repectively. The default is 8K.
-
-
-*** SMALL TCMALLOC CACHES: TRADING SPACE FOR TIME
-
-You can set a compiler directive that makes tcmalloc use less memory
-for overhead, at the cost of some time.
-
-Internally, tcmalloc keeps information about some of its internal data
-structures in a cache. This speeds memory operations that need to
-access this internal data. We've added a new, experimental flag to
-tcmalloc that reduces the size of this cache, decresaing the memory
-needs of applications using tcmalloc.
-
-This feature is still very experimental; it's not even a configure
-flag yet. To build libtcmalloc with smaller internal caches, run
-
- ./configure <normal flags> CXXFLAGS=-DTCMALLOC_SMALL_BUT_SLOW
-
-(or add -DTCMALLOC_SMALL_BUT_SLOW to your existing CXXFLAGS argument).
-
-
-*** NOTE FOR ___tls_get_addr ERROR
-
-When compiling perftools on some old systems, like RedHat 8, you may
-get an error like this:
- ___tls_get_addr: symbol not found
-
-This means that you have a system where some parts are updated enough
-to support Thread Local Storage, but others are not. The perftools
-configure script can't always detect this kind of case, leading to
-that error. To fix it, just comment out the line
- #define HAVE_TLS 1
-in your config.h file before building.
-
-
-*** TCMALLOC AND DLOPEN
-
-To improve performance, we use the "initial exec" model of Thread
-Local Storage in tcmalloc. The price for this is the library will not
-work correctly if it is loaded via dlopen(). This should not be a
-problem, since loading a malloc-replacement library via dlopen is
-asking for trouble in any case: some data will be allocated with one
-malloc, some with another. If, for some reason, you *do* need to use
-dlopen on tcmalloc, the easiest way is to use a version of tcmalloc
-with TLS turned off; see the ___tls_get_addr note above.
-
-
-*** COMPILING ON NON-LINUX SYSTEMS
-
-Perftools has been tested on the following systems:
- FreeBSD 6.0 (x86)
- FreeBSD 8.1 (x86_64)
- Linux CentOS 5.5 (x86_64)
- Linux Debian 4.0 (PPC)
- Linux Debian 5.0 (x86)
- Linux Fedora Core 3 (x86)
- Linux Fedora Core 4 (x86)
- Linux Fedora Core 5 (x86)
- Linux Fedora Core 6 (x86)
- Linux Fedora Core 13 (x86_64)
- Linux Fedora Core 14 (x86_64)
- Linux RedHat 9 (x86)
- Linux Slackware 13 (x86_64)
- Linux Ubuntu 6.06.1 (x86)
- Linux Ubuntu 6.06.1 (x86_64)
- Linux Ubuntu 10.04 (x86)
- Linux Ubuntu 10.10 (x86_64)
- Mac OS X 10.3.9 (Panther) (PowerPC)
- Mac OS X 10.4.8 (Tiger) (PowerPC)
- Mac OS X 10.4.8 (Tiger) (x86)
- Mac OS X 10.5 (Leopard) (x86)
- Mac OS X 10.6 (Snow Leopard) (x86)
- Solaris 10 (x86_64)
- Windows XP, Visual Studio 2003 (VC++ 7.1) (x86)
- Windows XP, Visual Studio 2005 (VC++ 8) (x86)
- Windows XP, Visual Studio 2005 (VC++ 9) (x86)
- Windows XP, Visual Studio 2005 (VC++ 10) (x86)
- Windows XP, MinGW 5.1.3 (x86)
- Windows XP, Cygwin 5.1 (x86)
-
-It works in its full generality on the Linux systems
-tested (though see 64-bit notes above). Portions of perftools work on
-the other systems. The basic memory-allocation library,
-tcmalloc_minimal, works on all systems. The cpu-profiler also works
-fairly widely. However, the heap-profiler and heap-checker are not
-yet as widely supported. In general, the 'configure' script will
-detect what OS you are building for, and only build the components
-that work on that OS.
-
-Note that tcmalloc_minimal is perfectly usable as a malloc/new
-replacement, so it is possible to use tcmalloc on all the systems
-above, by linking in libtcmalloc_minimal.
-
-** FreeBSD:
-
- The following binaries build and run successfully (creating
- libtcmalloc_minimal.so and libprofile.so in the process):
- % ./configure
- % make tcmalloc_minimal_unittest tcmalloc_minimal_large_unittest \
- addressmap_unittest atomicops_unittest frag_unittest \
- low_level_alloc_unittest markidle_unittest memalign_unittest \
- packed_cache_test stacktrace_unittest system_alloc_unittest \
- thread_dealloc_unittest profiler_unittest.sh
- % ./tcmalloc_minimal_unittest # to run this test
- % [etc] # to run other tests
-
- Three caveats: first, frag_unittest tries to allocate 400M of memory,
- and if you have less virtual memory on your system, the test may
- fail with a bad_alloc exception.
-
- Second, profiler_unittest.sh sometimes fails in the "fork" test.
- This is because stray SIGPROF signals from the parent process are
- making their way into the child process. (This may be a kernel
- bug that only exists in older kernels.) The profiling code itself
- is working fine. This only affects programs that call fork(); for
- most programs, the cpu profiler is entirely safe to use.
-
- Third, perftools depends on /proc to get shared library
- information. If you are running a FreeBSD system without proc,
- perftools will not be able to map addresses to functions. Some
- unittests will fail as a result.
-
- Finally, the new test introduced in perftools-1.2,
- profile_handler_unittest, fails on FreeBSD. It has something to do
- with how the itimer works. The cpu profiler test passes, so I
- believe the functionality is correct and the issue is with the test
- somehow. If anybody is an expert on itimers and SIGPROF in
- FreeBSD, and would like to debug this, I'd be glad to hear the
- results!
-
- libtcmalloc.so successfully builds, and the "advanced" tcmalloc
- functionality all works except for the leak-checker, which has
- Linux-specific code:
- % make heap-profiler_unittest.sh maybe_threads_unittest.sh \
- tcmalloc_unittest tcmalloc_both_unittest \
- tcmalloc_large_unittest # THESE WORK
- % make -k heap-checker_unittest.sh \
- heap-checker-death_unittest.sh # THESE DO NOT
-
- Note that unless you specify --enable-heap-checker explicitly,
- 'make' will not build the heap-checker unittests on a FreeBSD
- system.
-
- I have not tested other *BSD systems, but they are probably similar.
-
-** Mac OS X:
-
- I've tested OS X 10.5 [Leopard], OS X 10.4 [Tiger] and OS X 10.3
- [Panther] on both intel (x86) and PowerPC systems. For Panther
- systems, perftools does not work at all: it depends on a header
- file, OSAtomic.h, which is new in 10.4. (It's possible to get the
- code working for Panther/i386 without too much work; if you're
- interested in exploring this, drop an e-mail.)
-
- For the other seven systems, the binaries and libraries that
- successfully build are exactly the same as for FreeBSD. See that
- section for a list of binaries and instructions on building them.
-
- In addition, it appears OS X regularly fails profiler_unittest.sh
- in the "thread" test (in addition to occassionally failing in the
- "fork" test). It looks like OS X often delivers the profiling
- signal to the main thread, even when it's sleeping, rather than
- spawned threads that are doing actual work. If anyone knows
- details of how OS X handles SIGPROF (via setitimer()) events with
- threads, and has insight into this problem, please send mail to
- google-perftools@googlegroups.com.
-
-** Solaris 10 x86:
-
- I've only tested using the GNU C++ compiler, not the Sun C++
- compiler. Using g++ requires setting the PATH appropriately when
- configuring.
-
- % PATH=${PATH}:/usr/sfw/bin/:/usr/ccs/bin ./configure
- % PATH=${PATH}:/usr/sfw/bin/:/usr/ccs/bin make [...]
-
- Again, the binaries and libraries that successfully build are
- exactly the same as for FreeBSD. (However, while libprofiler.so can
- be used to generate profiles, pprof is not very successful at
- reading them -- necessary helper programs like nm don't seem
- to be installed by default on Solaris, or perhaps are only
- installed as part of the Sun C++ compiler package.) See that
- section for a list of binaries, and instructions on building them.
-
-** Windows (MSVC, Cygwin, and MinGW):
-
- Work on Windows is rather preliminary: only tcmalloc_minimal is
- supported.
-
- We haven't found a good way to get stack traces in release mode on
- windows (that is, when FPO is enabled), so the heap profiling may
- not be reliable in that case. Also, heap-checking and CPU profiling
- do not yet work at all. But as in other ports, the basic tcmalloc
- library functionality, overriding malloc and new and such (and even
- windows-specific functions like _aligned_malloc!), is working fine,
- at least with VC++ 7.1 (Visual Studio 2003) through VC++ 10.0,
- in both debug and release modes. See README.windows for
- instructions on how to install on Windows using Visual Studio.
-
- Cygwin can compile some but not all of perftools. Furthermore,
- there is a problem with exception-unwinding in cygwin (it can call
- malloc, which can call the exception-unwinding-setup code, which
- can lead to an infinite loop). I've comitted a workaround to the
- exception unwinding problem, but it only works in debug mode and
- when statically linking in tcmalloc. I hope to have a more proper
- fix in a later release. To configure under cygwin, run
-
- ./configure --disable-shared CXXFLAGS=-g && make
-
- Most of cygwin will compile (cygwin doesn't allow weak symbols, so
- the heap-checker and a few other pieces of functionality will not
- compile). 'make' will compile those libraries and tests that can
- be compiled. You can run 'make check' to make sure the basic
- functionality is working. I've heard reports that some versions of
- cygwin fail calls to pthread_join() with EINVAL, causing several
- tests to fail. If you have any insight into this, please mail
- google-perftools@googlegroups.com.
-
- This Windows functionality is also available using MinGW and Msys,
- In this case, you can use the regular './configure && make'
- process. 'make install' should also work. The Makefile will limit
- itself to those libraries and binaries that work on windows.
-
-
-Basic Installation
-==================
-
- These are generic installation instructions.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
- It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring. (Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.)
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
- The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'. You only need
-`configure.ac' if you want to change it or regenerate `configure' using
-a newer version of `autoconf'.
-
-The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system. If you're
- using `csh' on an old version of System V, you might need to type
- `sh ./configure' instead to prevent `csh' from trying to execute
- `configure' itself.
-
- Running `configure' takes awhile. While running, it prints some
- messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package.
-
- 4. Type `make install' to install the programs and any data files and
- documentation.
-
- 5. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
-Compilers and Options
-=====================
-
- Some systems require unusual options for compilation or linking that
-the `configure' script does not know about. Run `./configure --help'
-for details on some of the pertinent environment variables.
-
- You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment. Here
-is an example:
-
- ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
-
- *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
- You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
- If you have to use a `make' that does not support the `VPATH'
-variable, you have to compile the package for one architecture at a
-time in the source code directory. After you have installed the
-package for one architecture, use `make distclean' before reconfiguring
-for another architecture.
-
-Installation Names
-==================
-
- By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc. You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
- In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
-kinds of files. Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
- Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
- There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on. Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
-`--build=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
- CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
- OS KERNEL-OS
-
- See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
- If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
-produce code for.
-
- If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
- If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
- Variables not defined in a site shell script can be set in the
-environment passed to `configure'. However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost. In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'. For example:
-
- ./configure CC=/usr/local2/bin/gcc
-
-will cause the specified gcc to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-`configure' Invocation
-======================
-
- `configure' recognizes the following options to control how it
-operates.
-
-`--help'
-`-h'
- Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`--cache-file=FILE'
- Enable the cache: use and save the results of the tests in FILE,
- traditionally `config.cache'. FILE defaults to `/dev/null' to
- disable caching.
-
-`--config-cache'
-`-C'
- Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made. To
- suppress all normal output, redirect it to `/dev/null' (any error
- messages will still be shown).
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options. Run
-`configure --help' for more details.
diff --git a/src/third_party/gperftools-2.5/NEWS b/src/third_party/gperftools-2.5/NEWS
deleted file mode 100644
index fc81a7a6922..00000000000
--- a/src/third_party/gperftools-2.5/NEWS
+++ /dev/null
@@ -1,724 +0,0 @@
-== 12 Mar 2016 ==
-
-gperftools 2.5 is out!
-
-Just single bugfix was merged after rc2. Which was fix for issue #777.
-
-== 5 Mar 2016 ==
-
-gperftools 2.5rc2 is out!
-
-New release contains just few commits on top of first release
-candidate. One of them is build fix for Visual Studio. Another
-significant change is that dynamic sized delete is now disabled by
-default. It turned out that IFUNC relocations are not supporting our
-advanced use case on all platforms and in all cases.
-
-== 21 Feb 2016 ==
-
-gperftools 2.5rc is out!
-
-Here are major changes since 2.4:
-
-* we've moved to github!
-
-* Bryan Chan has contributed s390x support
-
-* stacktrace capturing via libgcc's _Unwind_Backtrace was implemented
- (for architectures with missing or broken libunwind).
-
-* "emergency malloc" was implemented. Which unbreaks recursive calls
- to malloc/free from stacktrace capturing functions (such us glib'c
- backtrace() or libunwind on arm). It is enabled by
- --enable-emergency-malloc configure flag or by default on arm when
- --enable-stacktrace-via-backtrace is given. It is another fix for a
- number common issues people had on platforms with missing or broken
- libunwind.
-
-* C++14 sized-deallocation is now supported (on gcc 5 and recent
- clangs). It is off by default and can be enabled at configure time
- via --enable-sized-delete. On GNU/Linux it can also be enabled at
- run-time by either TCMALLOC_ENABLE_SIZED_DELETE environment variable
- or by defining tcmalloc_sized_delete_enabled function which should
- return 1 to enable it.
-
-* we've lowered default value of transfer batch size to 512. Previous
- value (bumped up in 2.1) was too high and caused performance
- regression for some users. 512 should still give us performance
- boost for workloads that need higher transfer batch size while not
- penalizing other workloads too much.
-
-* Brian Silverman's patch finally stopped arming profiling timer
- unless profiling is started.
-
-* Andrew Morrow has contributed support for obtaining cache size of the
- current thread and softer idling (for use in MongoDB).
-
-* we've implemented few minor performance improvements, particularly
- on malloc fast-path.
-
-A number of smaller fixes were made. Many of them were contributed:
-
-* issue that caused spurious profiler_unittest.sh failures was fixed.
-
-* Jonathan Lambrechts contributed improved callgrind format support to
- pprof.
-
-* Matt Cross contributed better support for debug symbols in separate
- files to pprof.
-
-* Matt Cross contributed support for printing collapsed stack frame
- from pprof aimed at producing flame graphs.
-
-* Angus Gratton has contributed documentation fix mentioning that on
- windows only tcmalloc_minimal is supported.
-
-* Anton Samokhvalov has made tcmalloc use mi_force_{un,}lock on OSX
- instead of pthread_atfork. Which apparently fixes forking
- issues tcmalloc had on OSX.
-
-* Milton Chiang has contributed support for building 32-bit gperftools
- on arm8.
-
-* Patrick LoPresti has contributed support for specifying alternative
- profiling signal via CPUPROFILE_TIMER_SIGNAL environment variable.
-
-* Paolo Bonzini has contributed support configuring filename for
- sending malloc tracing output via TCMALLOC_TRACE_FILE environment
- variable.
-
-* user spotrh has enabled use of futex on arm.
-
-* user mitchblank has contributed better declaration for arg-less
- profiler functions.
-
-* Tom Conerly contributed proper freeing of memory allocated in
- HeapProfileTable::FillOrderedProfile on error paths.
-
-* user fdeweerdt has contributed curl arguments handling fix in pprof
-
-* Frederik Mellbin fixed tcmalloc's idea of mangled new and delete
- symbols on windows x64
-
-* Dair Grant has contributed cacheline alignment for ThreadCache
- objects
-
-* Fredrik Mellbin has contributed updated windows/config.h for Visual
- Studio 2015 and other windows fixes.
-
-* we're not linking libpthread to libtcmalloc_minimal anymore. Instead
- libtcmalloc_minimal links to pthread symbols weakly. As a result
- single-threaded programs remain single-threaded when linking to or
- preloading libtcmalloc_minimal.so.
-
-* Boris Sazonov has contributed mips compilation fix and printf misue
- in pprof.
-
-* Adhemerval Zanella has contributed alignment fixes for statically
- allocated variables.
-
-* Jens Rosenboom has contributed fixes for heap-profiler_unittest.sh
-
-* gshirishfree has contributed better description for GetStats method.
-
-* cyshi has contributed spinlock pause fix.
-
-* Chris Mayo has contributed --docdir argument support for configure.
-
-* Duncan Sands has contributed fix for function aliases.
-
-* Simon Que contributed better include for malloc_hook_c.h
-
-* user wmamrak contributed struct timespec fix for Visual Studio 2015.
-
-* user ssubotin contributed typo in PrintAvailability code.
-
-
-== 10 Jan 2015 ==
-
-gperftools 2.4 is out! The code is exactly same as 2.4rc.
-
-== 28 Dec 2014 ==
-
-gperftools 2.4rc is out!
-
-Here are changes since 2.3:
-
-* enabled aggressive decommit option by default. It was found to
- significantly improve memory fragmentation with negligible impact on
- performance. (Thanks to investigation work performed by Adhemerval
- Zanella)
-
-* added ./configure flags for tcmalloc pagesize and tcmalloc
- allocation alignment. Larger page sizes have been reported to
- improve performance occasionally. (Patch by Raphael Moreira Zinsly)
-
-* sped-up hot-path of malloc/free. By about 5% on static library and
- about 10% on shared library. Mainly due to more efficient checking
- of malloc hooks.
-
-* improved stacktrace capturing in cpu profiler (due to issue found by
- Arun Sharma). As part of that issue pprof's handling of cpu profiles
- was also improved.
-
-== 7 Dec 2014 ==
-
-gperftools 2.3 is out!
-
-Here are changes since 2.3rc:
-
-* (issue 658) correctly close socketpair fds on failure (patch by glider)
-
-* libunwind integration can be disabled at configure time (patch by
- Raphael Moreira Zinsly)
-
-* libunwind integration is disabled by default for ppc64 (patch by
- Raphael Moreira Zinsly)
-
-* libunwind integration is force-disabled for OSX. It was not used by
- default anyways. Fixes compilation issue I saw.
-
-== 2 Nov 2014 ==
-
-gperftools 2.3rc is out!
-
-Most small improvements in this release were made to pprof tool.
-
-New experimental Linux-only (for now) cpu profiling mode is a notable
-big improvement.
-
-Here are notable changes since 2.2.1:
-
-* (issue-631) fixed debugallocation miscompilation on mmap-less
- platforms (courtesy of user iamxujian)
-
-* (issue-630) reference to wrong PROFILE (vs. correct CPUPROFILE)
- environment variable was fixed (courtesy of WenSheng He)
-
-* pprof now has option to display stack traces in output for heap
- checker (courtesy of Michael Pasieka)
-
-* (issue-636) pprof web command now works on mingw
-
-* (issue-635) pprof now handles library paths that contain spaces
- (courtesy of user mich...@sebesbefut.com)
-
-* (issue-637) pprof now has an option to not strip template arguments
- (patch by jiakai)
-
-* (issue-644) possible out-of-bounds access in GetenvBeforeMain was
- fixed (thanks to user abyss.7)
-
-* (issue-641) pprof now has an option --show_addresses (thanks to user
- yurivict). New option prints instruction address in addition to
- function name in stack traces
-
-* (issue-646) pprof now works around some issues of addr2line
- reportedly when DWARF v4 format is used (patch by Adam McNeeney)
-
-* (issue-645) heap profiler exit message now includes remaining memory
- allocated info (patch by user yurivict)
-
-* pprof code that finds location of /proc/<pid>/maps in cpu profile
- files is now fixed (patch by Ricardo M. Correia)
-
-* (issue-654) pprof now handles "split text segments" feature of
- Chromium for Android. (patch by simonb)
-
-* (issue-655) potential deadlock on windows caused by early call to
- getenv in malloc initialization code was fixed (bug reported and fix
- proposed by user zndmitry)
-
-* incorrect detection of arm 6zk instruction set support
- (-mcpu=arm1176jzf-s) was fixed. (Reported by pedronavf on old
- issue-493)
-
-* new cpu profiling mode on Linux is now implemented. It sets up
- separate profiling timers for separate threads. Which improves
- accuracy of profiling on Linux a lot. It is off by default. And is
- enabled if both librt.f is loaded and CPUPROFILE_PER_THREAD_TIMERS
- environment variable is set. But note that all threads need to be
- registered via ProfilerRegisterThread.
-
-== 21 Jun 2014 ==
-
-gperftools 2.2.1 is out!
-
-Here's list of fixes:
-
-* issue-626 was closed. Which fixes initialization statically linked
- tcmalloc.
-
-* issue 628 was closed. It adds missing header file into source
- tarball. This fixes for compilation on PPC Linux.
-
-== 3 May 2014 ==
-
-gperftools 2.2 is out!
-
-Here are notable changes since 2.2rc:
-
-* issue 620 (crash on windows when c runtime dll is reloaded) was
- fixed
-
-== 19 Apr 2014 ==
-
-gperftools 2.2rc is out!
-
-Here are notable changes since 2.1:
-
-* a number of fixes for a number compilers and platforms. Notably
- Visual Studio 2013, recent mingw with c++ threads and some OSX
- fixes.
-
-* we now have mips and mips64 support! (courtesy of Jovan Zelincevic,
- Jean Lee, user xiaoyur347 and others)
-
-* we now have aarch64 (aka arm64) support! (contributed by Riku
- Voipio)
-
-* there's now support for ppc64-le (by Raphael Moreira Zinsly and
- Adhemerval Zanella)
-
-* there's now some support of uclibc (contributed by user xiaoyur347)
-
-* google/ headers will now give you deprecation warning. They are
- deprecated since 2.0
-
-* there's now new api: tc_malloc_skip_new_handler (ported from chromium
- fork)
-
-* issue-557: added support for dumping heap profile via signal (by
- Jean Lee)
-
-* issue-567: Petr Hosek contributed SysAllocator support for windows
-
-* Joonsoo Kim contributed several speedups for central freelist code
-
-* TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES environment variable now works
-
-* configure scripts are now using AM_MAINTAINER_MODE. It'll only
- affect folks who modify source from .tar.gz and want automake to
- automatically rebuild Makefile-s. See automake documentation for
- that.
-
-* issue-586: detect main executable even if PIE is active (based on
- patch by user themastermind1). Notably, it fixes profiler use with
- ruby.
-
-* there is now support for switching backtrace capturing method at
- runtime (via TCMALLOC_STACKTRACE_METHOD and
- TCMALLOC_STACKTRACE_METHOD_VERBOSE environment variables)
-
-* there is new backtrace capturing method using -finstrument-functions
- prologues contributed by user xiaoyur347
-
-* few cases of crashes/deadlocks in profiler were addressed. See
- (famous) issue-66, issue-547 and issue-579.
-
-* issue-464 (memory corruption in debugalloc's realloc after
- memallign) is now fixed
-
-* tcmalloc is now able to release memory back to OS on windows
- (issue-489). The code was ported from chromium fork (by a number of
- authors).
-
-* Together with issue-489 we ported chromium's "aggressive decommit"
- mode. In this mode (settable via malloc extension and via
- environment variable TCMALLOC_AGGRESSIVE_DECOMMIT), free pages are
- returned back to OS immediately.
-
-* MallocExtension::instance() is now faster (based on patch by
- Adhemerval Zanella)
-
-* issue-610 (hangs on windows in multibyte locales) is now fixed
-
-The following people helped with ideas or patches (based on git log,
-some contributions purely in bugtracker might be missing): Andrew
-C. Morrow, yurivict, Wang YanQing, Thomas Klausner,
-davide.italiano@10gen.com, Dai MIKURUBE, Joon-Sung Um, Jovan
-Zelincevic, Jean Lee, Petr Hosek, Ben Avison, drussel, Joonsoo Kim,
-Hannes Weisbach, xiaoyur347, Riku Voipio, Adhemerval Zanella, Raphael
-Moreira Zinsly
-
-== 30 July 2013 ==
-
-gperftools 2.1 is out!
-
-Just few fixes where merged after rc. Most notably:
-
-* Some fixes for debug allocation on POWER/Linux
-
-== 20 July 2013 ==
-
-gperftools 2.1rc is out!
-
-As a result of more than a year of contributions we're ready for 2.1
-release.
-
-But before making that step I'd like to create RC and make sure people
-have chance to test it.
-
-Here are notable changes since 2.0:
-
-* fixes for building on newer platforms. Notably, there's now initial
- support for x32 ABI (--enable-minimal only at this time))
-
-* new getNumericProperty stats for cache sizes
-
-* added HEAP_PROFILER_TIME_INTERVAL variable (see documentation)
-
-* added environment variable to control heap size (TCMALLOC_HEAP_LIMIT_MB)
-
-* added environment variable to disable release of memory back to OS
- (TCMALLOC_DISABLE_MEMORY_RELEASE)
-
-* cpu profiler can now be switched on and off by sending it a signal
- (specified in CPUPROFILESIGNAL)
-
-* (issue 491) fixed race-ful spinlock wake-ups
-
-* (issue 496) added some support for fork-ing of process that is using
- tcmalloc
-
-* (issue 368) improved memory fragmentation when large chunks of
- memory are allocated/freed
-
-== 03 February 2012 ==
-
-I've just released gperftools 2.0
-
-The `google-perftools` project has been renamed to `gperftools`. I
-(csilvers) am stepping down as maintainer, to be replaced by
-David Chappelle. Welcome to the team, David! David has been an
-an active contributor to perftools in the past -- in fact, he's the
-only person other than me that already has commit status. I am
-pleased to have him take over as maintainer.
-
-I have both renamed the project (the Google Code site renamed a few
-weeks ago), and bumped the major version number up to 2, to reflect
-the new community ownership of the project. Almost all the
-[http://gperftools.googlecode.com/svn/tags/gperftools-2.0/ChangeLog changes]
-are related to the renaming.
-
-The main functional change from google-perftools 1.10 is that
-I've renamed the `google/` include-directory to be `gperftools/`
-instead. New code should `#include <gperftools/tcmalloc.h>`/etc.
-(Most users of perftools don't need any perftools-specific includes at
-all, so this is mostly directed to "power users.") I've kept the old
-names around as forwarding headers to the new, so `#include
-<google/tcmalloc.h>` will continue to work.
-
-(The other functional change which I snuck in is getting rid of some
-bash-isms in one of the unittest driver scripts, so it could run on
-Solaris.)
-
-Note that some internal names still contain the text `google`, such as
-the `google_malloc` internal linker section. I think that's a
-trickier transition, and can happen in a future release (if at all).
-
-
-=== 31 January 2012 ===
-
-I've just released perftools 1.10
-
-There is an API-incompatible change: several of the methods in the
-`MallocExtension` class have changed from taking a `void*` to taking a
-`const void*`. You should not be affected by this API change
-unless you've written your own custom malloc extension that derives
-from `MallocExtension`, but since it is a user-visible change, I have
-upped the `.so` version number for this release.
-
-This release focuses on improvements to linux-syscall-support.h,
-including ARM and PPC fixups and general cleanups. I hope this will
-magically fix an array of bugs people have been seeing.
-
-There is also exciting news on the porting front, with support for
-patching win64 assembly contributed by IBM Canada! This is an
-important step -- perhaps the most difficult -- to getting perftools
-to work on 64-bit windows using the patching technique (it doesn't
-affect the libc-modification technique). `premable_patcher_test` has
-been added to help test these changes; it is meant to compile under
-x86_64, and won't work under win32.
-
-For the full list of changes, including improved `HEAP_PROFILE_MMAP`
-support, see the
-[http://gperftools.googlecode.com/svn/tags/google-perftools-1.10/ChangeLog ChangeLog].
-
-
-=== 24 January 2011 ===
-
-The `google-perftools` Google Code page has been renamed to
-`gperftools`, in preparation for the project being renamed to
-`gperftools`. In the coming weeks, I'll be stepping down as
-maintainer for the perftools project, and as part of that Google is
-relinquishing ownership of the project; it will now be entirely
-community run. The name change reflects that shift. The 'g' in
-'gperftools' stands for 'great'. :-)
-
-=== 23 December 2011 ===
-
-I've just released perftools 1.9.1
-
-I missed including a file in the tarball, that is needed to compile on
-ARM. If you are not compiling on ARM, or have successfully compiled
-perftools 1.9, there is no need to upgrade.
-
-
-=== 22 December 2011 ===
-
-I've just released perftools 1.9
-
-This change has a slew of improvements, from better ARM and freebsd
-support, to improved performance by moving some code outside of locks,
-to better pprof reporting of code with overloaded functions.
-
-The full list of changes is in the
-[http://google-perftools.googlecode.com/svn/tags/google-perftools-1.9/ChangeLog ChangeLog].
-
-
-=== 26 August 2011 ===
-
-I've just released perftools 1.8.3
-
-The star-crossed 1.8 series continues; in 1.8.1, I had accidentally
-removed some code that was needed for FreeBSD. (Without this code
-many apps would crash at startup.) This release re-adds that code.
-If you are not on FreeBSD, or are using FreeBSD with perftools 1.8 or
-earlier, there is no need to upgrade.
-
-=== 11 August 2011 ===
-
-I've just released perftools 1.8.2
-
-I was incorrectly calculating the patch-level in the configuration
-step, meaning the TC_VERSION_PATCH #define in tcmalloc.h was wrong.
-Since the testing framework checks for this, it was failing. Now it
-should work again. This time, I was careful to re-run my tests after
-upping the version number. :-)
-
-If you don't care about the TC_VERSION_PATCH #define, there's no
-reason to upgrae.
-
-=== 26 July 2011 ===
-
-I've just released perftools 1.8.1
-
-I was missing an #include that caused the build to break under some
-compilers, especially newer gcc's, that wanted it. This only affects
-people who build from source, so only the .tar.gz file is updated from
-perftools 1.8. If you didn't have any problems compiling perftools
-1.8, there's no reason to upgrade.
-
-=== 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/google-perftools-1.8/ChangeLog ChangeLog].
-
-
-=== 7 February 2011 ===
-
-Thanks to endlessr..., who
-[http://code.google.com/p/google-perftools/issues/detail?id=307 identified]
-why some tests were failing under MSVC 10 in release mode. It does not look
-like these failures point toward any problem with tcmalloc itself; rather, the
-problem is with the test, which made some assumptions that broke under the
-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 ===
-
-I've just released perftools 1.7
-
-I apologize for the delay since the last release; so many great new
-patches and bugfixes kept coming in (and are still coming in; I also
-apologize to those folks who have to slip until the next release). I
-picked this arbitrary time to make a cut.
-
-Among the many new features in this release is a multi-megabyte
-reduction in the amount of tcmalloc overhead uder x86_64, improved
-performance in the case of contention, and many many bugfixes,
-especially architecture-specific bugfixes. See the
-[http://google-perftools.googlecode.com/svn/tags/google-perftools-1.7/ChangeLog ChangeLog]
-for full details.
-
-One architecture-specific change of note is added comments in the
-[http://google-perftools.googlecode.com/svn/tags/perftools-1.7/README README]
-for using tcmalloc under OS X. I'm trying to get my head around the
-exact behavior of the OS X linker, and hope to have more improvements
-for the next release, but I hope these notes help folks who have been
-having trouble with tcmalloc on OS X.
-
-*Windows users*: I've heard reports that some unittests fail on
-Windows when compiled with MSVC 10 in Release mode. All tests pass in
-Debug mode. I've not heard of any problems with earlier versions of
-MSVC. I don't know if this is a problem with the runtime patching (so
-the static patching discussed in README_windows.txt will still work),
-a problem with perftools more generally, or a bug in MSVC 10. Anyone
-with windows expertise that can debug this, I'd be glad to hear from!
-
-
-=== 5 August 2010 ===
-
-I've just released perftools 1.6
-
-This version also has a large number of minor changes, including
-support for `malloc_usable_size()` as a glibc-compatible alias to
-`malloc_size()`, the addition of SVG-based output to `pprof`, and
-experimental support for tcmalloc large pages, which may speed up
-tcmalloc at the cost of greater memory use. To use tcmalloc large
-pages, see the
-[http://google-perftools.googlecode.com/svn/tags/perftools-1.6/INSTALL
-INSTALL file]; for all changes, see the
-[http://google-perftools.googlecode.com/svn/tags/perftools-1.6/ChangeLog
-ChangeLog].
-
-OS X NOTE: improvements in the profiler unittest have turned up an OS
-X issue: in multithreaded programs, it seems that OS X often delivers
-the profiling signal (from sigitimer()) to the main thread, even when
-it's sleeping, rather than spawned threads that are doing actual work.
-If anyone knows details of how OS X handles SIGPROF events (from
-setitimer) in threaded programs, and has insight into this problem,
-please send mail to google-perftools@googlegroups.com.
-
-To see if you're affected by this, look for profiling time that pprof
-attributes to `___semwait_signal`. This is work being done in other
-threads, that is being attributed to sleeping-time in the main thread.
-
-
-=== 20 January 2010 ===
-
-I've just released perftools 1.5
-
-This version has a slew of changes, leading to somewhat faster
-performance and improvements in portability. It adds features like
-`ITIMER_REAL` support to the cpu profiler, and `tc_set_new_mode` to
-mimic the windows function of the same name. Full details are in the
-[http://google-perftools.googlecode.com/svn/tags/perftools-1.5/ChangeLog
-ChangeLog].
-
-
-=== 11 September 2009 ===
-
-I've just released perftools 1.4
-
-The major change this release is the addition of a debugging malloc
-library! If you link with `libtcmalloc_debug.so` instead of
-`libtcmalloc.so` (and likewise for the `minimal` variants) you'll get
-a debugging malloc, which will catch double-frees, writes to freed
-data, `free`/`delete` and `delete`/`delete[]` mismatches, and even
-(optionally) writes past the end of an allocated block.
-
-We plan to do more with this library in the future, including
-supporting it on Windows, and adding the ability to use the debugging
-library with your default malloc in addition to using it with
-tcmalloc.
-
-There are also the usual complement of bug fixes, documented in the
-ChangeLog, and a few minor user-tunable knobs added to components like
-the system allocator.
-
-
-=== 9 June 2009 ===
-
-I've just released perftools 1.3
-
-Like 1.2, this has a variety of bug fixes, especially related to the
-Windows build. One of my bugfixes is to undo the weird `ld -r` fix to
-`.a` files that I introduced in perftools 1.2: it caused problems on
-too many platforms. I've reverted back to normal `.a` files. To work
-around the original problem that prompted the `ld -r` fix, I now
-provide `libtcmalloc_and_profiler.a`, for folks who want to link in
-both.
-
-The most interesting API change is that I now not only override
-`malloc`/`free`/etc, I also expose them via a unique set of symbols:
-`tc_malloc`/`tc_free`/etc. This enables clients to write their own
-memory wrappers that use tcmalloc:
-{{{
- void* malloc(size_t size) { void* r = tc_malloc(size); Log(r); return r; }
-}}}
-
-
-=== 17 April 2009 ===
-
-I've just released perftools 1.2.
-
-This is mostly a bugfix release. The major change is internal: I have
-a new system for creating packages, which allows me to create 64-bit
-packages. (I still don't do that for perftools, because there is
-still no great 64-bit solution, with libunwind still giving problems
-and --disable-frame-pointers not practical in every environment.)
-
-Another interesting change involves Windows: a
-[http://code.google.com/p/google-perftools/issues/detail?id=126 new
-patch] allows users to choose to override malloc/free/etc on Windows
-rather than patching, as is done now. This can be used to create
-custom CRTs.
-
-My fix for this
-[http://groups.google.com/group/google-perftools/browse_thread/thread/1ff9b50043090d9d/a59210c4206f2060?lnk=gst&q=dynamic#a59210c4206f2060
-bug involving static linking] ended up being to make libtcmalloc.a and
-libperftools.a a big .o file, rather than a true `ar` archive. This
-should not yield any problems in practice -- in fact, it should be
-better, since the heap profiler, leak checker, and cpu profiler will
-now all work even with the static libraries -- but if you find it
-does, please file a bug report.
-
-Finally, the profile_handler_unittest provided in the perftools
-testsuite (new in this release) is failing on FreeBSD. The end-to-end
-test that uses the profile-handler is passing, so I suspect the
-problem may be with the test, not the perftools code itself. However,
-I do not know enough about how itimers work on FreeBSD to be able to
-debug it. If you can figure it out, please let me know!
-
-=== 11 March 2009 ===
-
-I've just released perftools 1.1!
-
-It has many changes since perftools 1.0 including
-
- * Faster performance due to dynamically sized thread caches
- * Better heap-sampling for more realistic profiles
- * Improved support on Windows (MSVC 7.1 and cygwin)
- * Better stacktraces in linux (using VDSO)
- * Many bug fixes and feature requests
-
-Note: if you use the CPU-profiler with applications that fork without
-doing an exec right afterwards, please see the README. Recent testing
-has shown that profiles are unreliable in that case. The problem has
-existed since the first release of perftools. We expect to have a fix
-for perftools 1.2. For more details, see
-[http://code.google.com/p/google-perftools/issues/detail?id=105 issue 105].
-
-Everyone who uses perftools 1.0 is encouraged to upgrade to perftools
-1.1. If you see any problems with the new release, please file a bug
-report at http://code.google.com/p/google-perftools/issues/list.
-
-Enjoy!
diff --git a/src/third_party/gperftools-2.5/README b/src/third_party/gperftools-2.5/README
deleted file mode 100644
index 6b99ea8aa79..00000000000
--- a/src/third_party/gperftools-2.5/README
+++ /dev/null
@@ -1,283 +0,0 @@
-gperftools
-----------
-(originally Google Performance Tools)
-
-The fastest malloc we’ve seen; works particularly well with threads
-and STL. Also: thread-friendly heap-checker, heap-profiler, and
-cpu-profiler.
-
-
-OVERVIEW
----------
-
-gperftools is a collection of a high-performance multi-threaded
-malloc() implementation, plus some pretty nifty performance analysis
-tools.
-
-gperftools is distributed under the terms of the BSD License. Join our
-mailing list at gpeftools@googlegroups.com for updates.
-
-gperftools was original home for pprof program. But do note that
-original pprof (which is still included with gerftools) is now
-deprecated in favor of golang version at https://github.com/google/pprof
-
-
-TCMALLOC
---------
-Just link in -ltcmalloc or -ltcmalloc_minimal to get the advantages of
-tcmalloc -- a replacement for malloc and new. See below for some
-environment variables you can use with tcmalloc, as well.
-
-tcmalloc functionality is available on all systems we've tested; see
-INSTALL for more details. See README_windows.txt for instructions on
-using tcmalloc on Windows.
-
-NOTE: When compiling with programs with gcc, that you plan to link
-with libtcmalloc, it's safest to pass in the flags
-
- -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
-
-when compiling. gcc makes some optimizations assuming it is using its
-own, built-in malloc; that assumption obviously isn't true with
-tcmalloc. In practice, we haven't seen any problems with this, but
-the expected risk is highest for users who register their own malloc
-hooks with tcmalloc (using gperftools/malloc_hook.h). The risk is
-lowest for folks who use tcmalloc_minimal (or, of course, who pass in
-the above flags :-) ).
-
-
-HEAP PROFILER
--------------
-See doc/heap-profiler.html for information about how to use tcmalloc's
-heap profiler and analyze its output.
-
-As a quick-start, do the following after installing this package:
-
-1) Link your executable with -ltcmalloc
-2) Run your executable with the HEAPPROFILE environment var set:
- $ HEAPPROFILE=/tmp/heapprof <path/to/binary> [binary args]
-3) Run pprof to analyze the heap usage
- $ pprof <path/to/binary> /tmp/heapprof.0045.heap # run 'ls' to see options
- $ pprof --gv <path/to/binary> /tmp/heapprof.0045.heap
-
-You can also use LD_PRELOAD to heap-profile an executable that you
-didn't compile.
-
-There are other environment variables, besides HEAPPROFILE, you can
-set to adjust the heap-profiler behavior; c.f. "ENVIRONMENT VARIABLES"
-below.
-
-The heap profiler is available on all unix-based systems we've tested;
-see INSTALL for more details. It is not currently available on Windows.
-
-
-HEAP CHECKER
-------------
-See doc/heap-checker.html for information about how to use tcmalloc's
-heap checker.
-
-In order to catch all heap leaks, tcmalloc must be linked *last* into
-your executable. The heap checker may mischaracterize some memory
-accesses in libraries listed after it on the link line. For instance,
-it may report these libraries as leaking memory when they're not.
-(See the source code for more details.)
-
-Here's a quick-start for how to use:
-
-As a quick-start, do the following after installing this package:
-
-1) Link your executable with -ltcmalloc
-2) Run your executable with the HEAPCHECK environment var set:
- $ HEAPCHECK=1 <path/to/binary> [binary args]
-
-Other values for HEAPCHECK: normal (equivalent to "1"), strict, draconian
-
-You can also use LD_PRELOAD to heap-check an executable that you
-didn't compile.
-
-The heap checker is only available on Linux at this time; see INSTALL
-for more details.
-
-
-CPU PROFILER
-------------
-See doc/cpu-profiler.html for information about how to use the CPU
-profiler and analyze its output.
-
-As a quick-start, do the following after installing this package:
-
-1) Link your executable with -lprofiler
-2) Run your executable with the CPUPROFILE environment var set:
- $ CPUPROFILE=/tmp/prof.out <path/to/binary> [binary args]
-3) Run pprof to analyze the CPU usage
- $ pprof <path/to/binary> /tmp/prof.out # -pg-like text output
- $ pprof --gv <path/to/binary> /tmp/prof.out # really cool graphical output
-
-There are other environment variables, besides CPUPROFILE, you can set
-to adjust the cpu-profiler behavior; cf "ENVIRONMENT VARIABLES" below.
-
-The CPU profiler is available on all unix-based systems we've tested;
-see INSTALL for more details. It is not currently available on Windows.
-
-NOTE: CPU profiling doesn't work after fork (unless you immediately
- do an exec()-like call afterwards). Furthermore, if you do
- fork, and the child calls exit(), it may corrupt the profile
- data. You can use _exit() to work around this. We hope to have
- a fix for both problems in the next release of perftools
- (hopefully perftools 1.2).
-
-
-EVERYTHING IN ONE
------------------
-If you want the CPU profiler, heap profiler, and heap leak-checker to
-all be available for your application, you can do:
- gcc -o myapp ... -lprofiler -ltcmalloc
-
-However, if you have a reason to use the static versions of the
-library, this two-library linking won't work:
- gcc -o myapp ... /usr/lib/libprofiler.a /usr/lib/libtcmalloc.a # errors!
-
-Instead, use the special libtcmalloc_and_profiler library, which we
-make for just this purpose:
- gcc -o myapp ... /usr/lib/libtcmalloc_and_profiler.a
-
-
-CONFIGURATION OPTIONS
----------------------
-For advanced users, there are several flags you can pass to
-'./configure' that tweak tcmalloc performace. (These are in addition
-to the environment variables you can set at runtime to affect
-tcmalloc, described below.) See the INSTALL file for details.
-
-
-ENVIRONMENT VARIABLES
----------------------
-The cpu profiler, heap checker, and heap profiler will lie dormant,
-using no memory or CPU, until you turn them on. (Thus, there's no
-harm in linking -lprofiler into every application, and also -ltcmalloc
-assuming you're ok using the non-libc malloc library.)
-
-The easiest way to turn them on is by setting the appropriate
-environment variables. We have several variables that let you
-enable/disable features as well as tweak parameters.
-
-Here are some of the most important variables:
-
-HEAPPROFILE=<pre> -- turns on heap profiling and dumps data using this prefix
-HEAPCHECK=<type> -- turns on heap checking with strictness 'type'
-CPUPROFILE=<file> -- turns on cpu profiling and dumps data to this file.
-PROFILESELECTED=1 -- if set, cpu-profiler will only profile regions of code
- surrounded with ProfilerEnable()/ProfilerDisable().
-CPUPROFILE_FREQUENCY=x-- how many interrupts/second the cpu-profiler samples.
-
-TCMALLOC_DEBUG=<level> -- the higher level, the more messages malloc emits
-MALLOCSTATS=<level> -- prints memory-use stats at program-exit
-
-For a full list of variables, see the documentation pages:
- doc/cpuprofile.html
- doc/heapprofile.html
- doc/heap_checker.html
-
-
-COMPILING ON NON-LINUX SYSTEMS
-------------------------------
-
-Perftools was developed and tested on x86 Linux systems, and it works
-in its full generality only on those systems. However, we've
-successfully ported much of the tcmalloc library to FreeBSD, Solaris
-x86, and Darwin (Mac OS X) x86 and ppc; and we've ported the basic
-functionality in tcmalloc_minimal to Windows. See INSTALL for details.
-See README_windows.txt for details on the Windows port.
-
-
-PERFORMANCE
------------
-
-If you're interested in some third-party comparisons of tcmalloc to
-other malloc libraries, here are a few web pages that have been
-brought to our attention. The first discusses the effect of using
-various malloc libraries on OpenLDAP. The second compares tcmalloc to
-win32's malloc.
- http://www.highlandsun.com/hyc/malloc/
- http://gaiacrtn.free.fr/articles/win32perftools.html
-
-It's possible to build tcmalloc in a way that trades off faster
-performance (particularly for deletes) at the cost of more memory
-fragmentation (that is, more unusable memory on your system). See the
-INSTALL file for details.
-
-
-OLD SYSTEM ISSUES
------------------
-
-When compiling perftools on some old systems, like RedHat 8, you may
-get an error like this:
- ___tls_get_addr: symbol not found
-
-This means that you have a system where some parts are updated enough
-to support Thread Local Storage, but others are not. The perftools
-configure script can't always detect this kind of case, leading to
-that error. To fix it, just comment out (or delete) the line
- #define HAVE_TLS 1
-in your config.h file before building.
-
-
-64-BIT ISSUES
--------------
-
-There are two issues that can cause program hangs or crashes on x86_64
-64-bit systems, which use the libunwind library to get stack-traces.
-Neither issue should affect the core tcmalloc library; they both
-affect the perftools tools such as cpu-profiler, heap-checker, and
-heap-profiler.
-
-1) Some libc's -- at least glibc 2.4 on x86_64 -- have a bug where the
-libc function dl_iterate_phdr() acquires its locks in the wrong
-order. This bug should not affect tcmalloc, but may cause occasional
-deadlock with the cpu-profiler, heap-profiler, and heap-checker.
-Its likeliness increases the more dlopen() commands an executable has.
-Most executables don't have any, though several library routines like
-getgrgid() call dlopen() behind the scenes.
-
-2) On x86-64 64-bit systems, while tcmalloc itself works fine, the
-cpu-profiler tool is unreliable: it will sometimes work, but sometimes
-cause a segfault. I'll explain the problem first, and then some
-workarounds.
-
-Note that this only affects the cpu-profiler, which is a
-gperftools feature you must turn on manually by setting the
-CPUPROFILE environment variable. If you do not turn on cpu-profiling,
-you shouldn't see any crashes due to perftools.
-
-The gory details: The underlying problem is in the backtrace()
-function, which is a built-in function in libc.
-Backtracing is fairly straightforward in the normal case, but can run
-into problems when having to backtrace across a signal frame.
-Unfortunately, the cpu-profiler uses signals in order to register a
-profiling event, so every backtrace that the profiler does crosses a
-signal frame.
-
-In our experience, the only time there is trouble is when the signal
-fires in the middle of pthread_mutex_lock. pthread_mutex_lock is
-called quite a bit from system libraries, particularly at program
-startup and when creating a new thread.
-
-The solution: The dwarf debugging format has support for 'cfi
-annotations', which make it easy to recognize a signal frame. Some OS
-distributions, such as Fedora and gentoo 2007.0, already have added
-cfi annotations to their libc. A future version of libunwind should
-recognize these annotations; these systems should not see any
-crashses.
-
-Workarounds: If you see problems with crashes when running the
-cpu-profiler, consider inserting ProfilerStart()/ProfilerStop() into
-your code, rather than setting CPUPROFILE. This will profile only
-those sections of the codebase. Though we haven't done much testing,
-in theory this should reduce the chance of crashes by limiting the
-signal generation to only a small part of the codebase. Ideally, you
-would not use ProfilerStart()/ProfilerStop() around code that spawns
-new threads, or is otherwise likely to cause a call to
-pthread_mutex_lock!
-
----
-17 May 2011
diff --git a/src/third_party/gperftools-2.5/README_windows.txt b/src/third_party/gperftools-2.5/README_windows.txt
deleted file mode 100644
index 7bba12201e0..00000000000
--- a/src/third_party/gperftools-2.5/README_windows.txt
+++ /dev/null
@@ -1,120 +0,0 @@
---- COMPILING
-
-This project has begun being ported to Windows, only tcmalloc_minimal
-is supported at this time. A working solution file exists in this
-directory:
- gperftools.sln
-
-You can load this solution file into VC++ 7.1 (Visual Studio 2003) or
-later -- in the latter case, it will automatically convert the files
-to the latest format for you.
-
-When you build the solution, it will create a number of unittests,
-which you can run by hand (or, more easily, under the Visual Studio
-debugger) to make sure everything is working properly on your system.
-The binaries will end up in a directory called "debug" or "release" in
-the top-level directory (next to the .sln file). It will also create
-two binaries, nm-pdb and addr2line-pdb, which you should install in
-the same directory you install the 'pprof' perl script.
-
-I don't know very much about how to install DLLs on Windows, so you'll
-have to figure out that part for yourself. If you choose to just
-re-use the existing .sln, make sure you set the IncludeDir's
-appropriately! Look at the properties for libtcmalloc_minimal.dll.
-
-Note that these systems are set to build in Debug mode by default.
-You may want to change them to Release mode.
-
-To use tcmalloc_minimal in your own projects, you should only need to
-build the dll and install it someplace, so you can link it into
-further binaries. To use the dll, you need to add the following to
-the linker line of your executable:
- "libtcmalloc_minimal.lib" /INCLUDE:"__tcmalloc"
-
-Here is how to accomplish this in Visual Studio 2005 (VC8):
-
-1) Have your executable depend on the tcmalloc library by selecting
- "Project Dependencies..." from the "Project" menu. Your executable
- should depend on "libtcmalloc_minimal".
-
-2) Have your executable depend on a tcmalloc symbol -- this is
- necessary so the linker doesn't "optimize out" the libtcmalloc
- dependency -- by right-clicking on your executable's project (in
- the solution explorer), selecting Properties from the pull-down
- menu, then selecting "Configuration Properties" -> "Linker" ->
- "Input". Then, in the "Force Symbol References" field, enter the
- text "__tcmalloc" (without the quotes). Be sure to do this for both
- debug and release modes!
-
-You can also link tcmalloc code in statically -- see the example
-project tcmalloc_minimal_unittest-static, which does this. For this
-to work, you'll need to add "/D PERFTOOLS_DLL_DECL=" to the compile
-line of every perftools .cc file. You do not need to depend on the
-tcmalloc symbol in this case (that is, you don't need to do either
-step 1 or step 2 from above).
-
-An alternative to all the above is to statically link your application
-with libc, and then replace its malloc with tcmalloc. This allows you
-to just build and link your program normally; the tcmalloc support
-comes in a post-processing step. This is more reliable than the above
-technique (which depends on run-time patching, which is inherently
-fragile), though more work to set up. For details, see
- https://groups.google.com/group/google-perftools/browse_thread/thread/41cd3710af85e57b
-
-
---- THE HEAP-PROFILER
-
-The heap-profiler has had a preliminary port to Windows but does not
-build on Windows by default. It has not been well tested, and
-probably does not work at all when Frame Pointer Optimization (FPO) is
-enabled -- that is, in release mode. The other features of perftools,
-such as the cpu-profiler and leak-checker, have not yet been ported to
-Windows at all.
-
-
---- WIN64
-
-The function-patcher has to disassemble code, and is very
-x86-specific. However, the rest of perftools should work fine for
-both x86 and x64. In particular, if you use the 'statically link with
-libc, and replace its malloc with tcmalloc' approach, mentioned above,
-it should be possible to use tcmalloc with 64-bit windows.
-
-As of perftools 1.10, there is some support for disassembling x86_64
-instructions, for work with win64. This work is preliminary, but the
-test file preamble_patcher_test.cc is provided to play around with
-that a bit. preamble_patcher_test will not compile on win32.
-
-
---- ISSUES
-
-NOTE FOR WIN2K USERS: According to reports
-(http://code.google.com/p/gperftools/issues/detail?id=127)
-the stack-tracing necessary for the heap-profiler does not work on
-Win2K. The best workaround is, if you are building on a Win2k system
-is to add "/D NO_TCMALLOC_SAMPLES=" to your build, to turn off the
-stack-tracing. You will not be able to use the heap-profiler if you
-do this.
-
-NOTE ON _MSIZE and _RECALLOC: The tcmalloc version of _msize returns
-the size of the region tcmalloc allocated for you -- which is at least
-as many bytes you asked for, but may be more. (btw, these *are* bytes
-you own, even if you didn't ask for all of them, so it's correct code
-to access all of them if you want.) Unfortunately, the Windows CRT
-_recalloc() routine assumes that _msize returns exactly as many bytes
-as were requested. As a result, _recalloc() may not zero out new
-bytes correctly. IT'S SAFEST NOT TO USE _RECALLOC WITH TCMALLOC.
-_recalloc() is a tricky routine to use in any case (it's not safe to
-use with realloc, for instance).
-
-
-I have little experience with Windows programming, so there may be
-better ways to set this up than I've done! If you run across any
-problems, please post to the google-perftools Google Group, or report
-them on the gperftools Google Code site:
- http://groups.google.com/group/google-perftools
- http://code.google.com/p/gperftools/issues/list
-
--- craig
-
-Last modified: 2 February 2012
diff --git a/src/third_party/gperftools-2.5/SConscript b/src/third_party/gperftools-2.5/SConscript
deleted file mode 100644
index fd35f0c54d1..00000000000
--- a/src/third_party/gperftools-2.5/SConscript
+++ /dev/null
@@ -1,128 +0,0 @@
-# -*- mode: python -*-
-
-Import("env")
-Import("has_option")
-Import("debugBuild")
-
-env = env.Clone()
-
-files = [
- 'src/base/dynamic_annotations.c',
- 'src/base/elf_mem_image.cc',
- 'src/base/logging.cc',
- 'src/base/spinlock.cc',
- 'src/base/spinlock_internal.cc',
- 'src/base/sysinfo.cc',
- 'src/base/vdso_support.cc',
- 'src/central_freelist.cc',
- 'src/common.cc',
- 'src/internal_logging.cc',
- 'src/malloc_extension.cc',
- 'src/malloc_hook.cc',
- 'src/memfs_malloc.cc',
- 'src/page_heap.cc',
- 'src/sampler.cc',
- 'src/span.cc',
- 'src/stack_trace_table.cc',
- 'src/stacktrace.cc',
- 'src/static_vars.cc',
- 'src/symbolize.cc',
- 'src/thread_cache.cc',
- ]
-
-if env.TargetOSIs('windows'):
- files += [
- 'src/tcmalloc.cc',
- 'src/windows/port.cc',
- 'src/windows/system-alloc.cc',
- 'src/fake_stacktrace_scope.cc',
- ]
-else:
- files += [
- 'src/emergency_malloc_for_stacktrace.cc',
- 'src/maybe_threads.cc',
- 'src/system-alloc.cc',
- ]
-
- if not debugBuild:
- files += ['src/tcmalloc.cc'],
- else:
- files += ['src/debugallocation.cc']
-
-if has_option( 'use-cpu-profiler' ):
- files += [
- 'src/profile-handler.cc',
- 'src/profiledata.cc',
- 'src/profiler.cc',
- ]
-
-__malloc_hook_fragment = '''
-#include <malloc.h>
-void* (* volatile __malloc_hook)(size_t, const void*) = 0;
-'''
-
-def __checkMallocHookVolatile(check_context):
- check_context.Message("Checking if __malloc_hook is declared volatile... ")
- is_malloc_hook_volatile = check_context.TryCompile(__malloc_hook_fragment, '.cc')
- check_context.Result(is_malloc_hook_volatile)
- malloc_hook_define = 'MALLOC_HOOK_MAYBE_VOLATILE='
- if is_malloc_hook_volatile:
- malloc_hook_define += 'volatile'
- check_context.env.Append(CPPDEFINES=[malloc_hook_define])
-
-
-conf = Configure(env.Clone(), custom_tests=dict(CheckMallocHookVolatile=__checkMallocHookVolatile))
-conf.CheckMallocHookVolatile()
-
-if has_option('use-cpu-profiler'):
- if not conf.CheckLib('unwind', autoadd=False):
- env.ConfError("Compiling with --use-cpu-profiler requires having libunwind installed")
- conf.env.Append(
- CPPDEFINES=["NO_FRAME_POINTER", ("HAVE_LIBUNWIND_H", "1"), 'HAVE_UCONTEXT_H'],
- SYSLIBDEPS=['unwind']
- )
-
-env = conf.Finish()
-
-env.Append(CPPPATH=["build_" + env["TARGET_OS"] + "_" + env["TARGET_ARCH"]])
-
-env.Append(
- CPPDEFINES=["NO_HEAP_CHECK"],
-)
-
-# The build system doesn't define NDEBUG globally for historical reasons, however, TCMalloc
-# expects that NDEBUG is used to select between preferring the mmap or the sbrk allocator. For
-# non-debug builds, we want to prefer the sbrk allocator since this is TCMallocs preferred
-# production deployment configuration. See the use of NDEBUG and kDebugMode in
-# src/system-alloc.cc for more details.
-if not debugBuild:
- env.Append( CPPDEFINES=["NDEBUG"] )
-
-# For debug builds we want to capture stacks during (de)allocations,
-# but we don't want to pay that cost for release builds. For non-debug
-# builds we use NO_TCMALLOC_SAMPLES to disable the stack trace
-# collection. For debug builds we enable stack capture, but only on
-# intel targets, since tcmalloc's unwinder is very slow on other
-# platforms (see SERVER-28502).
-if (not debugBuild) or (not env['TARGET_ARCH'] in ['x86_64', 'i386']):
- env.Append(CPPDEFINES=["NO_TCMALLOC_SAMPLES"])
-
-env.Prepend( CPPPATH=["src/"] )
-
-def removeIfPresent(lst, item):
- try:
- lst.remove(item)
- except ValueError:
- pass
-
-for to_remove in ['-Werror', "-Wsign-compare","-Wall","-Werror=unused-result"]:
- removeIfPresent(env['CCFLAGS'], to_remove)
-
-# GCC on PowerPC under C++11 mode does not define __linux which gperftools depends on
-if env['TARGET_ARCH'] == 'ppc64le':
- env.Append( CPPDEFINES=[ "__linux"] )
-
-env.Library(
- target='tcmalloc_minimal',
- source=files,
-)
diff --git a/src/third_party/gperftools-2.5/TODO b/src/third_party/gperftools-2.5/TODO
deleted file mode 100644
index 550f7e09b9d..00000000000
--- a/src/third_party/gperftools-2.5/TODO
+++ /dev/null
@@ -1,47 +0,0 @@
-HEAP PROFILER
-
-1) Fix heap profiling under all STLs
- * Find out how to force non-glibc STL libraries to call new() and
- delete() for every allocation / deallocation.
- * Make heap profiler ignore STL-internal allocations for those
- libraries under which we cannot profile accurately, so we only
- see object-level leaks.
-2) Remove dependency on tcmalloc?
-3) Port to non-linux O/Ses (right now code uses /proc for library info)
-4) Port to non-x86 architectures (locking code in spinlock is x86-specific)
-5) Port to C?
-6) Figure out how to get setenv() to work properly before main() in
- shared libaries, and get rid of the profile-naming hack once we
- do. (See HeapProfiler::Init().)
-
-
-HEAP CHECKER
-
-1) Remove requirement that the heap-checker must be linked last into
- an application (hard! -- it needs its global constructor to run
- first)
-
-TCMALLOC
-
-1) Implement mallinfo/mallopt
-2) Have tcmalloc work correctly when libpthread is not linked in
- (currently working for glibc, could use other libc's too)
-3) Return memory to the system when requirements drop
-4) Explore coloring allocated objects to avoid cache conflicts
-5) Explore biasing reclamation to larger addresses
-6) Add contention stats to a synchronization.cc (can do spinlocks,
- but threads? -- may have to provide our own thread implementation)
-
-CPU PROFILER
-
-1) Figure out how to get setenv() to work properly before main() in
- shared libaries(), and get rid of the profile-naming hack once we
- do. (See Profiler::GetUniquePathFromEnv().)
-2) Resolve crashing problems on x86_64 (see README)
-
-STACKTRACE
-
-1) Remove dependency on linux/x86
-
----
-11 March 2008
diff --git a/src/third_party/gperftools-2.5/build_linux_aarch64/config.h b/src/third_party/gperftools-2.5/build_linux_aarch64/config.h
deleted file mode 100644
index a0ec388a09f..00000000000
--- a/src/third_party/gperftools-2.5/build_linux_aarch64/config.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* src/config.h.in. Generated from configure.ac by autoheader. */
-
-
-#ifndef GPERFTOOLS_CONFIG_H_
-#define GPERFTOOLS_CONFIG_H_
-
-
-/* Build runtime detection for sized delete */
-/* #undef ENABLE_DYNAMIC_SIZED_DELETE */
-
-/* Build sized deletion operators */
-/* #undef ENABLE_SIZED_DELETE */
-
-/* Define to 1 if compiler supports __builtin_expect */
-#define HAVE_BUILTIN_EXPECT 1
-
-/* Define to 1 if compiler supports __builtin_stack_pointer */
-/* #undef HAVE_BUILTIN_STACK_POINTER */
-
-/* Define to 1 if you have the <conflict-signal.h> header file. */
-/* #undef HAVE_CONFLICT_SIGNAL_H */
-
-/* Define to 1 if you have the <cygwin/signal.h> header file. */
-/* #undef HAVE_CYGWIN_SIGNAL_H */
-
-/* Define to 1 if you have the declaration of `backtrace', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_BACKTRACE */
-
-/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
- */
-#define HAVE_DECL_CFREE 1
-
-/* Define to 1 if you have the declaration of `memalign', and to 0 if you
- don't. */
-#define HAVE_DECL_MEMALIGN 1
-
-/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_NANOSLEEP */
-
-/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
- you don't. */
-#define HAVE_DECL_POSIX_MEMALIGN 1
-
-/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
- don't. */
-#define HAVE_DECL_PVALLOC 1
-
-/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't.
- */
-/* #undef HAVE_DECL_SLEEP */
-
-/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
- */
-#define HAVE_DECL_UNAME 1
-
-/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
- */
-#define HAVE_DECL_VALLOC 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if the system has the type `Elf32_Versym'. */
-#define HAVE_ELF32_VERSYM 1
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#define HAVE_EXECINFO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the <features.h> header file. */
-#define HAVE_FEATURES_H 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if you have the `geteuid' function. */
-#define HAVE_GETEUID 1
-
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1
-
-/* Define to 1 if you have the <glob.h> header file. */
-#define HAVE_GLOB_H 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-/* #undef HAVE_LIBUNWIND_H */
-
-/* Define to 1 if you have the <linux/ptrace.h> header file. */
-#define HAVE_LINUX_PTRACE_H 1
-
-/* Define if this is Linux that has SIGEV_THREAD_ID */
-#define HAVE_LINUX_SIGEV_THREAD_ID 1
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have a working `mmap' system call. */
-#define HAVE_MMAP 1
-
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* define if libc has program_invocation_name */
-#define HAVE_PROGRAM_INVOCATION_NAME 1
-
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD 1
-
-/* defined to 1 if pthread symbols are exposed even without include pthread.h
- */
-/* #undef HAVE_PTHREAD_DESPITE_ASKING_FOR */
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `sbrk' function. */
-#define HAVE_SBRK 1
-
-/* Define to 1 if you have the <sched.h> header file. */
-#define HAVE_SCHED_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if the system has the type `struct mallinfo'. */
-#define HAVE_STRUCT_MALLINFO 1
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#define HAVE_SYS_CDEFS_H 1
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#define HAVE_SYS_PRCTL_H 1
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#define HAVE_SYS_SYSCALL_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/ucontext.h> header file. */
-#define HAVE_SYS_UCONTEXT_H 1
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if compiler supports __thread */
-#define HAVE_TLS 1
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-#define HAVE_UCONTEXT_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Whether <unwind.h> contains _Unwind_Backtrace */
-#define HAVE_UNWIND_BACKTRACE 1
-
-/* Define to 1 if you have the <unwind.h> header file. */
-#define HAVE_UNWIND_H 1
-
-/* Define to 1 if you have the <valgrind.h> header file. */
-/* #undef HAVE_VALGRIND_H */
-
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__ 1
-
-/* Define to 1 if compiler supports __environ */
-#define HAVE___ENVIRON 1
-
-/* Define to 1 if the system has the type `__int64'. */
-/* #undef HAVE___INT64 */
-
-/* prefix where we look for installed files */
-#define INSTALL_PREFIX "/usr/local"
-
-/* Define to 1 if int32_t is equivalent to intptr_t */
-/* #undef INT32_EQUALS_INTPTR */
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 'volatile' if __malloc_hook is declared volatile */
-/* #undef MALLOC_HOOK_MAYBE_VOLATILE */
-
-/* Name of package */
-#define PACKAGE "gperftools"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gperftools@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gperftools"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gperftools 2.5"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gperftools"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.5"
-
-/* How to access the PC from a struct ucontext */
-#define PC_FROM_UCONTEXT uc_mcontext.pc
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#define PERFTOOLS_DLL_DECL /**/
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIdS "ld"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIuS "lu"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIxS "lx"
-
-/* 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 */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Define 32K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_32K_PAGES */
-
-/* Define 64K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_64K_PAGES */
-
-/* Define 8 bytes of allocation alignment for tcmalloc */
-/* #undef TCMALLOC_ALIGN_8BYTES */
-
-/* Version number of package */
-#define VERSION "2.5"
-
-/* C99 says: define this to get the PRI... macros from stdint.h */
-#ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-
-#ifdef __MINGW32__
-#include "windows/mingw.h"
-#endif
-
-#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */
-
diff --git a/src/third_party/gperftools-2.5/build_linux_ppc64le/config.h b/src/third_party/gperftools-2.5/build_linux_ppc64le/config.h
deleted file mode 100644
index 3b2546ed1a9..00000000000
--- a/src/third_party/gperftools-2.5/build_linux_ppc64le/config.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* src/config.h.in. Generated from configure.ac by autoheader. */
-
-
-#ifndef GPERFTOOLS_CONFIG_H_
-#define GPERFTOOLS_CONFIG_H_
-
-
-/* Build runtime detection for sized delete */
-/* #undef ENABLE_DYNAMIC_SIZED_DELETE */
-
-/* Build sized deletion operators */
-/* #undef ENABLE_SIZED_DELETE */
-
-/* Define to 1 if compiler supports __builtin_expect */
-#define HAVE_BUILTIN_EXPECT 1
-
-/* Define to 1 if compiler supports __builtin_stack_pointer */
-/* #undef HAVE_BUILTIN_STACK_POINTER */
-
-/* Define to 1 if you have the <conflict-signal.h> header file. */
-/* #undef HAVE_CONFLICT_SIGNAL_H */
-
-/* Define to 1 if you have the <cygwin/signal.h> header file. */
-/* #undef HAVE_CYGWIN_SIGNAL_H */
-
-/* Define to 1 if you have the declaration of `backtrace', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_BACKTRACE */
-
-/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
- */
-#define HAVE_DECL_CFREE 1
-
-/* Define to 1 if you have the declaration of `memalign', and to 0 if you
- don't. */
-#define HAVE_DECL_MEMALIGN 1
-
-/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_NANOSLEEP */
-
-/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
- you don't. */
-#define HAVE_DECL_POSIX_MEMALIGN 1
-
-/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
- don't. */
-#define HAVE_DECL_PVALLOC 1
-
-/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't.
- */
-/* #undef HAVE_DECL_SLEEP */
-
-/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
- */
-#define HAVE_DECL_UNAME 1
-
-/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
- */
-#define HAVE_DECL_VALLOC 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if the system has the type `Elf32_Versym'. */
-#define HAVE_ELF32_VERSYM 1
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#define HAVE_EXECINFO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the <features.h> header file. */
-#define HAVE_FEATURES_H 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if you have the `geteuid' function. */
-#define HAVE_GETEUID 1
-
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1
-
-/* Define to 1 if you have the <glob.h> header file. */
-#define HAVE_GLOB_H 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-/* #undef HAVE_LIBUNWIND_H */
-
-/* Define to 1 if you have the <linux/ptrace.h> header file. */
-#define HAVE_LINUX_PTRACE_H 1
-
-/* Define if this is Linux that has SIGEV_THREAD_ID */
-#define HAVE_LINUX_SIGEV_THREAD_ID 1
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have a working `mmap' system call. */
-#define HAVE_MMAP 1
-
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* define if libc has program_invocation_name */
-#define HAVE_PROGRAM_INVOCATION_NAME 1
-
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD 1
-
-/* defined to 1 if pthread symbols are exposed even without include pthread.h
- */
-/* #undef HAVE_PTHREAD_DESPITE_ASKING_FOR */
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `sbrk' function. */
-#define HAVE_SBRK 1
-
-/* Define to 1 if you have the <sched.h> header file. */
-#define HAVE_SCHED_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if the system has the type `struct mallinfo'. */
-#define HAVE_STRUCT_MALLINFO 1
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#define HAVE_SYS_CDEFS_H 1
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#define HAVE_SYS_PRCTL_H 1
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#define HAVE_SYS_SYSCALL_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/ucontext.h> header file. */
-#define HAVE_SYS_UCONTEXT_H 1
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if compiler supports __thread */
-#define HAVE_TLS 1
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-#define HAVE_UCONTEXT_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Whether <unwind.h> contains _Unwind_Backtrace */
-#define HAVE_UNWIND_BACKTRACE 1
-
-/* Define to 1 if you have the <unwind.h> header file. */
-#define HAVE_UNWIND_H 1
-
-/* Define to 1 if you have the <valgrind.h> header file. */
-/* #undef HAVE_VALGRIND_H */
-
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__ 1
-
-/* Define to 1 if compiler supports __environ */
-#define HAVE___ENVIRON 1
-
-/* Define to 1 if the system has the type `__int64'. */
-/* #undef HAVE___INT64 */
-
-/* prefix where we look for installed files */
-#define INSTALL_PREFIX "/usr/local"
-
-/* Define to 1 if int32_t is equivalent to intptr_t */
-/* #undef INT32_EQUALS_INTPTR */
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 'volatile' if __malloc_hook is declared volatile */
-/* #undef MALLOC_HOOK_MAYBE_VOLATILE */
-
-/* Name of package */
-#define PACKAGE "gperftools"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gperftools@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gperftools"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gperftools 2.5"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gperftools"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.5"
-
-/* How to access the PC from a struct ucontext */
-#define PC_FROM_UCONTEXT uc_mcontext.gp_regs[PT_NIP]
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#define PERFTOOLS_DLL_DECL /**/
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIdS "ld"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIuS "lu"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIxS "lx"
-
-/* 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 */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Define 32K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_32K_PAGES */
-
-/* Define 64K of internal pages size for tcmalloc */
-#define TCMALLOC_64K_PAGES 1
-
-/* Define 8 bytes of allocation alignment for tcmalloc */
-/* #undef TCMALLOC_ALIGN_8BYTES */
-
-/* Version number of package */
-#define VERSION "2.5"
-
-/* C99 says: define this to get the PRI... macros from stdint.h */
-#ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-
-#ifdef __MINGW32__
-#include "windows/mingw.h"
-#endif
-
-#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */
-
diff --git a/src/third_party/gperftools-2.5/build_linux_s390x/config.h b/src/third_party/gperftools-2.5/build_linux_s390x/config.h
deleted file mode 100644
index e363a8778b1..00000000000
--- a/src/third_party/gperftools-2.5/build_linux_s390x/config.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* src/config.h.in. Generated from configure.ac by autoheader. */
-
-
-#ifndef GPERFTOOLS_CONFIG_H_
-#define GPERFTOOLS_CONFIG_H_
-
-
-/* Build runtime detection for sized delete */
-/* #undef ENABLE_DYNAMIC_SIZED_DELETE */
-
-/* Build sized deletion operators */
-/* #undef ENABLE_SIZED_DELETE */
-
-/* Define to 1 if compiler supports __builtin_expect */
-#define HAVE_BUILTIN_EXPECT 1
-
-/* Define to 1 if compiler supports __builtin_stack_pointer */
-/* #undef HAVE_BUILTIN_STACK_POINTER */
-
-/* Define to 1 if you have the <conflict-signal.h> header file. */
-/* #undef HAVE_CONFLICT_SIGNAL_H */
-
-/* Define to 1 if you have the <cygwin/signal.h> header file. */
-/* #undef HAVE_CYGWIN_SIGNAL_H */
-
-/* Define to 1 if you have the declaration of `backtrace', and to 0 if you
- don't. */
-#define HAVE_DECL_BACKTRACE 1
-
-/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
- */
-#define HAVE_DECL_CFREE 1
-
-/* Define to 1 if you have the declaration of `memalign', and to 0 if you
- don't. */
-#define HAVE_DECL_MEMALIGN 1
-
-/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_NANOSLEEP */
-
-/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
- you don't. */
-#define HAVE_DECL_POSIX_MEMALIGN 1
-
-/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
- don't. */
-#define HAVE_DECL_PVALLOC 1
-
-/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't.
- */
-/* #undef HAVE_DECL_SLEEP */
-
-/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
- */
-#define HAVE_DECL_UNAME 1
-
-/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
- */
-#define HAVE_DECL_VALLOC 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if the system has the type `Elf32_Versym'. */
-#define HAVE_ELF32_VERSYM 1
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#define HAVE_EXECINFO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the <features.h> header file. */
-#define HAVE_FEATURES_H 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if you have the `geteuid' function. */
-#define HAVE_GETEUID 1
-
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1
-
-/* Define to 1 if you have the <glob.h> header file. */
-#define HAVE_GLOB_H 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-/* #undef HAVE_LIBUNWIND_H */
-
-/* Define to 1 if you have the <linux/ptrace.h> header file. */
-#define HAVE_LINUX_PTRACE_H 1
-
-/* Define if this is Linux that has SIGEV_THREAD_ID */
-#define HAVE_LINUX_SIGEV_THREAD_ID 1
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have a working `mmap' system call. */
-#define HAVE_MMAP 1
-
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* define if libc has program_invocation_name */
-#define HAVE_PROGRAM_INVOCATION_NAME 1
-
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD 1
-
-/* defined to 1 if pthread symbols are exposed even without include pthread.h
- */
-/* #undef HAVE_PTHREAD_DESPITE_ASKING_FOR */
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `sbrk' function. */
-#define HAVE_SBRK 1
-
-/* Define to 1 if you have the <sched.h> header file. */
-#define HAVE_SCHED_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if the system has the type `struct mallinfo'. */
-#define HAVE_STRUCT_MALLINFO 1
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#define HAVE_SYS_CDEFS_H 1
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#define HAVE_SYS_PRCTL_H 1
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#define HAVE_SYS_SYSCALL_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/ucontext.h> header file. */
-#define HAVE_SYS_UCONTEXT_H 1
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if compiler supports __thread */
-#define HAVE_TLS 1
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-#define HAVE_UCONTEXT_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Whether <unwind.h> contains _Unwind_Backtrace */
-#define HAVE_UNWIND_BACKTRACE 1
-
-/* Define to 1 if you have the <unwind.h> header file. */
-#define HAVE_UNWIND_H 1
-
-/* Define to 1 if you have the <valgrind.h> header file. */
-/* #undef HAVE_VALGRIND_H */
-
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__ 1
-
-/* Define to 1 if compiler supports __environ */
-#define HAVE___ENVIRON 1
-
-/* Define to 1 if the system has the type `__int64'. */
-/* #undef HAVE___INT64 */
-
-/* prefix where we look for installed files */
-#define INSTALL_PREFIX "/usr/local"
-
-/* Define to 1 if int32_t is equivalent to intptr_t */
-/* #undef INT32_EQUALS_INTPTR */
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 'volatile' if __malloc_hook is declared volatile */
-/* #undef MALLOC_HOOK_MAYBE_VOLATILE */
-
-/* Name of package */
-#define PACKAGE "gperftools"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gperftools@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gperftools"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gperftools 2.5"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gperftools"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.5"
-
-/* How to access the PC from a struct ucontext */
-#define PC_FROM_UCONTEXT uc_mcontext.psw.addr
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#define PERFTOOLS_DLL_DECL /**/
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIdS "ld"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIuS "lu"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIxS "lx"
-
-/* 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 */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Define 32K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_32K_PAGES */
-
-/* Define 64K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_64K_PAGES */
-
-/* Define 8 bytes of allocation alignment for tcmalloc */
-/* #undef TCMALLOC_ALIGN_8BYTES */
-
-/* Version number of package */
-#define VERSION "2.5"
-
-/* C99 says: define this to get the PRI... macros from stdint.h */
-#ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-
-#ifdef __MINGW32__
-#include "windows/mingw.h"
-#endif
-
-#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */
-
diff --git a/src/third_party/gperftools-2.5/build_linux_x86_64/config.h b/src/third_party/gperftools-2.5/build_linux_x86_64/config.h
deleted file mode 100644
index 6d5c5c30c3e..00000000000
--- a/src/third_party/gperftools-2.5/build_linux_x86_64/config.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* src/config.h.in. Generated from configure.ac by autoheader. */
-
-
-#ifndef GPERFTOOLS_CONFIG_H_
-#define GPERFTOOLS_CONFIG_H_
-
-
-/* Build runtime detection for sized delete */
-/* #undef ENABLE_DYNAMIC_SIZED_DELETE */
-
-/* Build sized deletion operators */
-/* #undef ENABLE_SIZED_DELETE */
-
-/* Define to 1 if compiler supports __builtin_expect */
-#define HAVE_BUILTIN_EXPECT 1
-
-/* Define to 1 if compiler supports __builtin_stack_pointer */
-/* #undef HAVE_BUILTIN_STACK_POINTER */
-
-/* Define to 1 if you have the <conflict-signal.h> header file. */
-/* #undef HAVE_CONFLICT_SIGNAL_H */
-
-/* Define to 1 if you have the <cygwin/signal.h> header file. */
-/* #undef HAVE_CYGWIN_SIGNAL_H */
-
-/* Define to 1 if you have the declaration of `backtrace', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_BACKTRACE */
-
-/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
- */
-#define HAVE_DECL_CFREE 1
-
-/* Define to 1 if you have the declaration of `memalign', and to 0 if you
- don't. */
-#define HAVE_DECL_MEMALIGN 1
-
-/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_NANOSLEEP */
-
-/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
- you don't. */
-#define HAVE_DECL_POSIX_MEMALIGN 1
-
-/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
- don't. */
-#define HAVE_DECL_PVALLOC 1
-
-/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't.
- */
-/* #undef HAVE_DECL_SLEEP */
-
-/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
- */
-#define HAVE_DECL_UNAME 1
-
-/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
- */
-#define HAVE_DECL_VALLOC 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if the system has the type `Elf32_Versym'. */
-#define HAVE_ELF32_VERSYM 1
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#define HAVE_EXECINFO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the <features.h> header file. */
-#define HAVE_FEATURES_H 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if you have the `geteuid' function. */
-#define HAVE_GETEUID 1
-
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1
-
-/* Define to 1 if you have the <glob.h> header file. */
-#define HAVE_GLOB_H 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-/* #undef HAVE_LIBUNWIND_H */
-
-/* Define to 1 if you have the <linux/ptrace.h> header file. */
-#define HAVE_LINUX_PTRACE_H 1
-
-/* Define if this is Linux that has SIGEV_THREAD_ID */
-#define HAVE_LINUX_SIGEV_THREAD_ID 1
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have a working `mmap' system call. */
-#define HAVE_MMAP 1
-
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* define if libc has program_invocation_name */
-#define HAVE_PROGRAM_INVOCATION_NAME 1
-
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD 1
-
-/* defined to 1 if pthread symbols are exposed even without include pthread.h
- */
-/* #undef HAVE_PTHREAD_DESPITE_ASKING_FOR */
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `sbrk' function. */
-#define HAVE_SBRK 1
-
-/* Define to 1 if you have the <sched.h> header file. */
-#define HAVE_SCHED_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if the system has the type `struct mallinfo'. */
-#define HAVE_STRUCT_MALLINFO 1
-
-/* Define to 1 if you have the <sys/cdefs.h> header file. */
-#define HAVE_SYS_CDEFS_H 1
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#define HAVE_SYS_PRCTL_H 1
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#define HAVE_SYS_SYSCALL_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/ucontext.h> header file. */
-/* #undef HAVE_SYS_UCONTEXT_H */
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if compiler supports __thread */
-#define HAVE_TLS 1
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-/* #undef HAVE_UCONTEXT_H */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Whether <unwind.h> contains _Unwind_Backtrace */
-#define HAVE_UNWIND_BACKTRACE 1
-
-/* Define to 1 if you have the <unwind.h> header file. */
-#define HAVE_UNWIND_H 1
-
-/* Define to 1 if you have the <valgrind.h> header file. */
-/* #undef HAVE_VALGRIND_H */
-
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__ 1
-
-/* Define to 1 if compiler supports __environ */
-#define HAVE___ENVIRON 1
-
-/* Define to 1 if the system has the type `__int64'. */
-/* #undef HAVE___INT64 */
-
-/* prefix where we look for installed files */
-#define INSTALL_PREFIX "/usr/local"
-
-/* Define to 1 if int32_t is equivalent to intptr_t */
-/* #undef INT32_EQUALS_INTPTR */
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 'volatile' if __malloc_hook is declared volatile */
-/* #undef MALLOC_HOOK_MAYBE_VOLATILE */
-
-/* Name of package */
-#define PACKAGE "gperftools"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gperftools@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gperftools"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gperftools 2.5"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gperftools"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.5"
-
-/* How to access the PC from a struct ucontext */
-#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP]
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#define PERFTOOLS_DLL_DECL /**/
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIdS "ld"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIuS "lu"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIxS "lx"
-
-/* 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 */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Define 32K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_32K_PAGES */
-
-/* Define 64K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_64K_PAGES */
-
-/* Define 8 bytes of allocation alignment for tcmalloc */
-/* #undef TCMALLOC_ALIGN_8BYTES */
-
-/* Version number of package */
-#define VERSION "2.5"
-
-/* C99 says: define this to get the PRI... macros from stdint.h */
-#ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-
-#ifdef __MINGW32__
-#include "windows/mingw.h"
-#endif
-
-#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */
-
diff --git a/src/third_party/gperftools-2.5/build_osx_x86_64/config.h b/src/third_party/gperftools-2.5/build_osx_x86_64/config.h
deleted file mode 100644
index 201d19d3099..00000000000
--- a/src/third_party/gperftools-2.5/build_osx_x86_64/config.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* src/config.h.in. Generated from configure.ac by autoheader. */
-
-
-#ifndef GPERFTOOLS_CONFIG_H_
-#define GPERFTOOLS_CONFIG_H_
-
-
-/* Build runtime detection for sized delete */
-/* #undef ENABLE_DYNAMIC_SIZED_DELETE */
-
-/* Build sized deletion operators */
-/* #undef ENABLE_SIZED_DELETE */
-
-/* Define to 1 if compiler supports __builtin_expect */
-#define HAVE_BUILTIN_EXPECT 1
-
-/* Define to 1 if compiler supports __builtin_stack_pointer */
-/* #undef HAVE_BUILTIN_STACK_POINTER */
-
-/* Define to 1 if you have the <conflict-signal.h> header file. */
-/* #undef HAVE_CONFLICT_SIGNAL_H */
-
-/* Define to 1 if you have the <cygwin/signal.h> header file. */
-/* #undef HAVE_CYGWIN_SIGNAL_H */
-
-/* Define to 1 if you have the declaration of `backtrace', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_BACKTRACE */
-
-/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
- */
-#define HAVE_DECL_CFREE 0
-
-/* Define to 1 if you have the declaration of `memalign', and to 0 if you
- don't. */
-#define HAVE_DECL_MEMALIGN 0
-
-/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_NANOSLEEP */
-
-/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
- you don't. */
-#define HAVE_DECL_POSIX_MEMALIGN 0
-
-/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
- don't. */
-#define HAVE_DECL_PVALLOC 0
-
-/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't.
- */
-/* #undef HAVE_DECL_SLEEP */
-
-/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
- */
-#define HAVE_DECL_UNAME 1
-
-/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
- */
-#define HAVE_DECL_VALLOC 0
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if the system has the type `Elf32_Versym'. */
-/* #undef HAVE_ELF32_VERSYM */
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#define HAVE_EXECINFO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the <features.h> header file. */
-/* #undef HAVE_FEATURES_H */
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if you have the `geteuid' function. */
-#define HAVE_GETEUID 1
-
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1
-
-/* Define to 1 if you have the <glob.h> header file. */
-#define HAVE_GLOB_H 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-#define HAVE_LIBUNWIND_H 1
-
-/* Define to 1 if you have the <linux/ptrace.h> header file. */
-/* #undef HAVE_LINUX_PTRACE_H */
-
-/* Define if this is Linux that has SIGEV_THREAD_ID */
-/* #undef HAVE_LINUX_SIGEV_THREAD_ID */
-
-/* Define to 1 if you have the <malloc.h> header file. */
-/* #undef HAVE_MALLOC_H */
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have a working `mmap' system call. */
-#define HAVE_MMAP 1
-
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* define if libc has program_invocation_name */
-/* #undef HAVE_PROGRAM_INVOCATION_NAME */
-
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD 1
-
-/* defined to 1 if pthread symbols are exposed even without include pthread.h
- */
-/* #undef HAVE_PTHREAD_DESPITE_ASKING_FOR */
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `sbrk' function. */
-#define HAVE_SBRK 1
-
-/* Define to 1 if you have the <sched.h> header file. */
-#define HAVE_SCHED_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* 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. */
-#define HAVE_SYS_CDEFS_H 1
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-/* #undef HAVE_SYS_PRCTL_H */
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#define HAVE_SYS_SYSCALL_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/ucontext.h> header file. */
-#define HAVE_SYS_UCONTEXT_H 1
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if compiler supports __thread */
-/* #undef HAVE_TLS */
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-/* #undef HAVE_UCONTEXT_H */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Whether <unwind.h> contains _Unwind_Backtrace */
-#define HAVE_UNWIND_BACKTRACE 1
-
-/* Define to 1 if you have the <unwind.h> header file. */
-#define HAVE_UNWIND_H 1
-
-/* Define to 1 if you have the <valgrind.h> header file. */
-/* #undef HAVE_VALGRIND_H */
-
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__ 1
-
-/* Define to 1 if compiler supports __environ */
-/* #undef HAVE___ENVIRON */
-
-/* Define to 1 if the system has the type `__int64'. */
-/* #undef HAVE___INT64 */
-
-/* prefix where we look for installed files */
-#define INSTALL_PREFIX "/usr/local"
-
-/* Define to 1 if int32_t is equivalent to intptr_t */
-/* #undef INT32_EQUALS_INTPTR */
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 'volatile' if __malloc_hook is declared volatile */
-/* #undef MALLOC_HOOK_MAYBE_VOLATILE */
-
-/* Name of package */
-#define PACKAGE "gperftools"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gperftools@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gperftools"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gperftools 2.5"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gperftools"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.5"
-
-/* How to access the PC from a struct ucontext */
-#define PC_FROM_UCONTEXT uc_mcontext->__ss.__rip
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#define PERFTOOLS_DLL_DECL /**/
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIdS "ld"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIuS "lu"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIxS "lx"
-
-/* 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 */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Define 32K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_32K_PAGES */
-
-/* Define 64K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_64K_PAGES */
-
-/* Define 8 bytes of allocation alignment for tcmalloc */
-/* #undef TCMALLOC_ALIGN_8BYTES */
-
-/* Version number of package */
-#define VERSION "2.5"
-
-/* C99 says: define this to get the PRI... macros from stdint.h */
-#ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-
-#ifdef __MINGW32__
-#include "windows/mingw.h"
-#endif
-
-#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */
-
diff --git a/src/third_party/gperftools-2.5/build_solaris_x86_64/config.h b/src/third_party/gperftools-2.5/build_solaris_x86_64/config.h
deleted file mode 100644
index 78256c13809..00000000000
--- a/src/third_party/gperftools-2.5/build_solaris_x86_64/config.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* src/config.h.in. Generated from configure.ac by autoheader. */
-
-
-#ifndef GPERFTOOLS_CONFIG_H_
-#define GPERFTOOLS_CONFIG_H_
-
-
-/* Build runtime detection for sized delete */
-/* #undef ENABLE_DYNAMIC_SIZED_DELETE */
-
-/* Build sized deletion operators */
-/* #undef ENABLE_SIZED_DELETE */
-
-/* Define to 1 if compiler supports __builtin_expect */
-#define HAVE_BUILTIN_EXPECT 1
-
-/* Define to 1 if compiler supports __builtin_stack_pointer */
-/* #undef HAVE_BUILTIN_STACK_POINTER */
-
-/* Define to 1 if you have the <conflict-signal.h> header file. */
-/* #undef HAVE_CONFLICT_SIGNAL_H */
-
-/* Define to 1 if you have the <cygwin/signal.h> header file. */
-/* #undef HAVE_CYGWIN_SIGNAL_H */
-
-/* Define to 1 if you have the declaration of `backtrace', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_BACKTRACE */
-
-/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
- */
-#define HAVE_DECL_CFREE 0
-
-/* Define to 1 if you have the declaration of `memalign', and to 0 if you
- don't. */
-#define HAVE_DECL_MEMALIGN 0
-
-/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you
- don't. */
-/* #undef HAVE_DECL_NANOSLEEP */
-
-/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
- you don't. */
-#define HAVE_DECL_POSIX_MEMALIGN 0
-
-/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
- don't. */
-#define HAVE_DECL_PVALLOC 0
-
-/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't.
- */
-/* #undef HAVE_DECL_SLEEP */
-
-/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
- */
-#define HAVE_DECL_UNAME 1
-
-/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
- */
-#define HAVE_DECL_VALLOC 0
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if the system has the type `Elf32_Versym'. */
-/* #undef HAVE_ELF32_VERSYM */
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#define HAVE_EXECINFO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the <features.h> header file. */
-/* #undef HAVE_FEATURES_H */
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if you have the `geteuid' function. */
-#define HAVE_GETEUID 1
-
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1
-
-/* Define to 1 if you have the <glob.h> header file. */
-#define HAVE_GLOB_H 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-/* #undef HAVE_LIBUNWIND_H */
-
-/* Define to 1 if you have the <linux/ptrace.h> header file. */
-/* #undef HAVE_LINUX_PTRACE_H */
-
-/* Define if this is Linux that has SIGEV_THREAD_ID */
-/* #undef HAVE_LINUX_SIGEV_THREAD_ID */
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have a working `mmap' system call. */
-#define HAVE_MMAP 1
-
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* define if libc has program_invocation_name */
-/* #undef HAVE_PROGRAM_INVOCATION_NAME */
-
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD 1
-
-/* defined to 1 if pthread symbols are exposed even without include pthread.h
- */
-#define HAVE_PTHREAD_DESPITE_ASKING_FOR 1
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `sbrk' function. */
-#define HAVE_SBRK 1
-
-/* Define to 1 if you have the <sched.h> header file. */
-#define HAVE_SCHED_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if the system has the type `struct mallinfo'. */
-#define HAVE_STRUCT_MALLINFO 1
-
-/* 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/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-/* #undef HAVE_SYS_PRCTL_H */
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#define HAVE_SYS_SYSCALL_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/ucontext.h> header file. */
-#define HAVE_SYS_UCONTEXT_H 1
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if compiler supports __thread */
-#define HAVE_TLS 1
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-#define HAVE_UCONTEXT_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Whether <unwind.h> contains _Unwind_Backtrace */
-#define HAVE_UNWIND_BACKTRACE 1
-
-/* Define to 1 if you have the <unwind.h> header file. */
-#define HAVE_UNWIND_H 1
-
-/* Define to 1 if you have the <valgrind.h> header file. */
-/* #undef HAVE_VALGRIND_H */
-
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__ 1
-
-/* Define to 1 if compiler supports __environ */
-/* #undef HAVE___ENVIRON */
-
-/* Define to 1 if the system has the type `__int64'. */
-/* #undef HAVE___INT64 */
-
-/* prefix where we look for installed files */
-#define INSTALL_PREFIX "/usr/local"
-
-/* Define to 1 if int32_t is equivalent to intptr_t */
-#define INT32_EQUALS_INTPTR 1
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 'volatile' if __malloc_hook is declared volatile */
-/* #undef MALLOC_HOOK_MAYBE_VOLATILE */
-
-/* Name of package */
-#define PACKAGE "gperftools"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gperftools@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gperftools"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gperftools 2.5"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gperftools"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.5"
-
-/* How to access the PC from a struct ucontext */
-#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_PC]
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#define PERFTOOLS_DLL_DECL /**/
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIdS "d"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIuS "u"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIxS "x"
-
-/* 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 */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Define 32K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_32K_PAGES */
-
-/* Define 64K of internal pages size for tcmalloc */
-/* #undef TCMALLOC_64K_PAGES */
-
-/* Define 8 bytes of allocation alignment for tcmalloc */
-/* #undef TCMALLOC_ALIGN_8BYTES */
-
-/* Version number of package */
-#define VERSION "2.5"
-
-/* C99 says: define this to get the PRI... macros from stdint.h */
-#ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-
-#ifdef __MINGW32__
-#include "windows/mingw.h"
-#endif
-
-#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */
-
diff --git a/src/third_party/gperftools-2.5/build_windows_x86_64/config.h b/src/third_party/gperftools-2.5/build_windows_x86_64/config.h
deleted file mode 100644
index 3fddad47c2f..00000000000
--- a/src/third_party/gperftools-2.5/build_windows_x86_64/config.h
+++ /dev/null
@@ -1,330 +0,0 @@
-/* A manual version of config.h fit for windows machines.
- *
- * Use of this source code is governed by a BSD-style license that can
- * be found in the LICENSE file.
- */
-
-/* Sometimes we accidentally #include this config.h instead of the one
- in .. -- this is particularly true for msys/mingw, which uses the
- unix config.h but also runs code in the windows directory.
- */
-#ifdef __MINGW32__
-#include "../config.h"
-#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_
-#endif
-
-#ifndef GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_
-#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_
-/* used by tcmalloc.h */
-#define GPERFTOOLS_CONFIG_H_
-
-/* define this if you are linking tcmalloc statically and overriding the
- * default allocators.
- * For instructions on how to use this mode, see
- * http://groups.google.com/group/google-perftools/browse_thread/thread/41cd3710af85e57b
- */
-#undef WIN32_OVERRIDE_ALLOCATORS
-
-/* Define to 1 if your libc has a snprintf implementation */
-#if defined(_MSC_VER) && _MSC_VER >= 1900
-#define HAVE_SNPRINTF 1
-#else
-#undef HAVE_SNPRINTF
-#endif
-
-/* Define to 1 if compiler supports __builtin_stack_pointer */
-#undef HAVE_BUILTIN_STACK_POINTER
-
-/* Define to 1 if you have the <conflict-signal.h> header file. */
-#undef HAVE_CONFLICT_SIGNAL_H
-
-/* Define to 1 if you have the <cygwin/signal.h> header file. */
-#undef HAVE_CYGWIN_SIGNAL_H
-
-/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
- */
-#undef HAVE_DECL_CFREE
-
-/* Define to 1 if you have the declaration of `memalign', and to 0 if you
- don't. */
-#undef HAVE_DECL_MEMALIGN
-
-/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
- you don't. */
-#undef HAVE_DECL_POSIX_MEMALIGN
-
-/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
- don't. */
-#undef HAVE_DECL_PVALLOC
-
-/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
- */
-#undef HAVE_DECL_UNAME
-
-/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
- */
-#undef HAVE_DECL_VALLOC
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if the system has the type `Elf32_Versym'. */
-#undef HAVE_ELF32_VERSYM
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#undef HAVE_EXECINFO_H
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
-/* Define to 1 if you have the <features.h> header file. */
-#undef HAVE_FEATURES_H
-
-/* Define to 1 if you have the `geteuid' function. */
-#undef HAVE_GETEUID
-
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1 /* we define it in windows/port.cc */
-
-/* Define to 1 if you have the <glob.h> header file. */
-#undef HAVE_GLOB_H
-
-/* Define to 1 if you have the <grp.h> header file. */
-#undef HAVE_GRP_H
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-#undef HAVE_LIBUNWIND_H
-
-/* Define to 1 if you have the <linux/ptrace.h> header file. */
-#undef HAVE_LINUX_PTRACE_H
-
-/* 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
-
-/* Define to 1 if you have a working `mmap' system call. */
-#undef HAVE_MMAP
-
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#undef HAVE_POLL_H
-
-/* define if libc has program_invocation_name */
-#undef HAVE_PROGRAM_INVOCATION_NAME
-
-/* Define if you have POSIX threads libraries and header files. */
-#undef HAVE_PTHREAD
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#undef HAVE_PWD_H
-
-/* Define to 1 if you have the `sbrk' function. */
-#undef HAVE_SBRK
-
-/* Define to 1 if you have the <sched.h> header file. */
-#undef HAVE_SCHED_H
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#if defined(_MSC_VER) && _MSC_VER >= 1900
-#define HAVE_STDINT_H 1
-#else
-#undef HAVE_STDINT_H
-#endif
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* 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
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#undef HAVE_SYS_PRCTL_H
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#undef HAVE_SYS_RESOURCE_H
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#undef HAVE_SYS_SOCKET_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#undef HAVE_SYS_SYSCALL_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* <sys/ucontext.h> is broken on redhat 7 */
-#undef HAVE_SYS_UCONTEXT_H
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#undef HAVE_SYS_WAIT_H
-
-/* Define to 1 if compiler supports __thread */
-#define HAVE_TLS 1
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-#undef HAVE_UCONTEXT_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the <unwind.h> header file. */
-#undef HAVE_UNWIND_H
-
-/* Define to 1 if you have the <valgrind.h> header file. */
-#undef HAVE_VALGRIND_H
-
-/* define if your compiler has __attribute__ */
-#undef HAVE___ATTRIBUTE__
-
-/* Define to 1 if compiler supports __environ */
-#undef HAVE___ENVIRON
-
-/* Define to 1 if the system has the type `__int64'. */
-#define HAVE___INT64 1
-
-/* prefix where we look for installed files */
-#undef INSTALL_PREFIX
-
-/* Define to 1 if int32_t is equivalent to intptr_t */
-#undef INT32_EQUALS_INTPTR
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#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
-
-/* Name of package */
-#define PACKAGE "gperftools"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gperftools@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gperftools"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gperftools 2.5"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gperftools"
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.5"
-
-/* How to access the PC from a struct ucontext */
-#undef PC_FROM_UCONTEXT
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-// MONGODB MODIFCATION - disable DLL exports
-#ifndef PERFTOOLS_DLL_DECL
-# define PERFTOOLS_IS_A_DLL 0 /* not set if you're statically linking */
-# define PERFTOOLS_DLL_DECL /**/
-# define PERFTOOLS_DLL_DECL_FOR_UNITTESTS /**/
-#endif
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIdS "Id"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIuS "Iu"
-
-/* 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
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Version number of package */
-#undef VERSION
-
-/* C99 says: define this to get the PRI... macros from stdint.h */
-#ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-#undef inline
-#endif
-
-// ---------------------------------------------------------------------
-// Extra stuff not found in config.h.in
-
-// This must be defined before the windows.h is included. We need at
-// least 0x0400 for mutex.h to have access to TryLock, and at least
-// 0x0501 for patch_functions.cc to have access to GetModuleHandleEx.
-// (This latter is an optimization we could take out if need be.)
-#ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0501
-#endif
-
-// We want to make sure not to ever try to #include heap-checker.h
-#define NO_HEAP_CHECK 1
-
-// TODO(csilvers): include windows/port.h in every relevant source file instead?
-#include "windows/port.h"
-
-// MONGODB MODIFCATION - disable DLL hook
-// gperftools/windows/patch_functions.cc normally defines this function,
-// but we do not link this file since it would dynamically patch our functions.
-// We override the behavior of this function to no-patch functions, but instead
-// simply to do nothing
-// TCMalloc calls this via a static initializer
-static void PatchWindowsFunctions() {
- // Intentionally left empty
-}
-#endif /* GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ */
diff --git a/src/third_party/gperftools-2.5/src/addressmap-inl.h b/src/third_party/gperftools-2.5/src/addressmap-inl.h
deleted file mode 100644
index fd1dc5b6ffe..00000000000
--- a/src/third_party/gperftools-2.5/src/addressmap-inl.h
+++ /dev/null
@@ -1,422 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-//
-// A fast map from addresses to values. Assumes that addresses are
-// clustered. The main use is intended to be for heap-profiling.
-// May be too memory-hungry for other uses.
-//
-// We use a user-defined allocator/de-allocator so that we can use
-// this data structure during heap-profiling.
-//
-// IMPLEMENTATION DETAIL:
-//
-// Some default definitions/parameters:
-// * Block -- aligned 128-byte region of the address space
-// * Cluster -- aligned 1-MB region of the address space
-// * Block-ID -- block-number within a cluster
-// * Cluster-ID -- Starting address of cluster divided by cluster size
-//
-// We use a three-level map to represent the state:
-// 1. A hash-table maps from a cluster-ID to the data for that cluster.
-// 2. For each non-empty cluster we keep an array indexed by
-// block-ID tht points to the first entry in the linked-list
-// for the block.
-// 3. At the bottom, we keep a singly-linked list of all
-// entries in a block (for non-empty blocks).
-//
-// hash table
-// +-------------+
-// | id->cluster |---> ...
-// | ... |
-// | id->cluster |---> Cluster
-// +-------------+ +-------+ Data for one block
-// | nil | +------------------------------------+
-// | ----+---|->[addr/value]-->[addr/value]-->... |
-// | nil | +------------------------------------+
-// | ----+--> ...
-// | nil |
-// | ... |
-// +-------+
-//
-// Note that we require zero-bytes of overhead for completely empty
-// clusters. The minimum space requirement for a cluster is the size
-// of the hash-table entry plus a pointer value for each block in
-// the cluster. Empty blocks impose no extra space requirement.
-//
-// The cost of a lookup is:
-// a. A hash-table lookup to find the cluster
-// b. An array access in the cluster structure
-// c. A traversal over the linked-list for a block
-
-#ifndef BASE_ADDRESSMAP_INL_H_
-#define BASE_ADDRESSMAP_INL_H_
-
-#include "config.h"
-#include <stddef.h>
-#include <string.h>
-#if defined HAVE_STDINT_H
-#include <stdint.h> // to get uint16_t (ISO naming madness)
-#elif defined HAVE_INTTYPES_H
-#include <inttypes.h> // another place uint16_t might be defined
-#else
-#include <sys/types.h> // our last best hope
-#endif
-
-// This class is thread-unsafe -- that is, instances of this class can
-// not be accessed concurrently by multiple threads -- because the
-// callback function for Iterate() may mutate contained values. If the
-// callback functions you pass do not mutate their Value* argument,
-// AddressMap can be treated as thread-compatible -- that is, it's
-// safe for multiple threads to call "const" methods on this class,
-// but not safe for one thread to call const methods on this class
-// while another thread is calling non-const methods on the class.
-template <class Value>
-class AddressMap {
- public:
- typedef void* (*Allocator)(size_t size);
- typedef void (*DeAllocator)(void* ptr);
- typedef const void* Key;
-
- // Create an AddressMap that uses the specified allocator/deallocator.
- // The allocator/deallocator should behave like malloc/free.
- // For instance, the allocator does not need to return initialized memory.
- AddressMap(Allocator alloc, DeAllocator dealloc);
- ~AddressMap();
-
- // If the map contains an entry for "key", return it. Else return NULL.
- inline const Value* Find(Key key) const;
- inline Value* FindMutable(Key key);
-
- // Insert <key,value> into the map. Any old value associated
- // with key is forgotten.
- void Insert(Key key, Value value);
-
- // Remove any entry for key in the map. If an entry was found
- // and removed, stores the associated value in "*removed_value"
- // and returns true. Else returns false.
- bool FindAndRemove(Key key, Value* removed_value);
-
- // Similar to Find but we assume that keys are addresses of non-overlapping
- // memory ranges whose sizes are given by size_func.
- // If the map contains a range into which "key" points
- // (at its start or inside of it, but not at the end),
- // return the address of the associated value
- // and store its key in "*res_key".
- // Else return NULL.
- // max_size specifies largest range size possibly in existence now.
- typedef size_t (*ValueSizeFunc)(const Value& v);
- const Value* FindInside(ValueSizeFunc size_func, size_t max_size,
- Key key, Key* res_key);
-
- // Iterate over the address map calling 'callback'
- // for all stored key-value pairs and passing 'arg' to it.
- // We don't use full Closure/Callback machinery not to add
- // unnecessary dependencies to this class with low-level uses.
- template<class Type>
- inline void Iterate(void (*callback)(Key, Value*, Type), Type arg) const;
-
- private:
- typedef uintptr_t Number;
-
- // The implementation assumes that addresses inserted into the map
- // will be clustered. We take advantage of this fact by splitting
- // up the address-space into blocks and using a linked-list entry
- // for each block.
-
- // Size of each block. There is one linked-list for each block, so
- // do not make the block-size too big. Oterwise, a lot of time
- // will be spent traversing linked lists.
- static const int kBlockBits = 7;
- static const int kBlockSize = 1 << kBlockBits;
-
- // Entry kept in per-block linked-list
- struct Entry {
- Entry* next;
- Key key;
- Value value;
- };
-
- // We further group a sequence of consecutive blocks into a cluster.
- // The data for a cluster is represented as a dense array of
- // linked-lists, one list per contained block.
- static const int kClusterBits = 13;
- static const Number kClusterSize = 1 << (kBlockBits + kClusterBits);
- static const int kClusterBlocks = 1 << kClusterBits;
-
- // We use a simple chaining hash-table to represent the clusters.
- struct Cluster {
- Cluster* next; // Next cluster in hash table chain
- Number id; // Cluster ID
- Entry* blocks[kClusterBlocks]; // Per-block linked-lists
- };
-
- // Number of hash-table entries. With the block-size/cluster-size
- // defined above, each cluster covers 1 MB, so an 4K entry
- // hash-table will give an average hash-chain length of 1 for 4GB of
- // in-use memory.
- static const int kHashBits = 12;
- static const int kHashSize = 1 << 12;
-
- // Number of entry objects allocated at a time
- static const int ALLOC_COUNT = 64;
-
- Cluster** hashtable_; // The hash-table
- Entry* free_; // Free list of unused Entry objects
-
- // Multiplicative hash function:
- // The value "kHashMultiplier" is the bottom 32 bits of
- // int((sqrt(5)-1)/2 * 2^32)
- // This is a good multiplier as suggested in CLR, Knuth. The hash
- // value is taken to be the top "k" bits of the bottom 32 bits
- // of the muliplied value.
- static const uint32_t kHashMultiplier = 2654435769u;
- static int HashInt(Number x) {
- // Multiply by a constant and take the top bits of the result.
- const uint32_t m = static_cast<uint32_t>(x) * kHashMultiplier;
- return static_cast<int>(m >> (32 - kHashBits));
- }
-
- // Find cluster object for specified address. If not found
- // and "create" is true, create the object. If not found
- // and "create" is false, return NULL.
- //
- // This method is bitwise-const if create is false.
- Cluster* FindCluster(Number address, bool create) {
- // Look in hashtable
- const Number cluster_id = address >> (kBlockBits + kClusterBits);
- const int h = HashInt(cluster_id);
- for (Cluster* c = hashtable_[h]; c != NULL; c = c->next) {
- if (c->id == cluster_id) {
- return c;
- }
- }
-
- // Create cluster if necessary
- if (create) {
- Cluster* c = New<Cluster>(1);
- c->id = cluster_id;
- c->next = hashtable_[h];
- hashtable_[h] = c;
- return c;
- }
- return NULL;
- }
-
- // Return the block ID for an address within its cluster
- static int BlockID(Number address) {
- return (address >> kBlockBits) & (kClusterBlocks - 1);
- }
-
- //--------------------------------------------------------------
- // Memory management -- we keep all objects we allocate linked
- // together in a singly linked list so we can get rid of them
- // when we are all done. Furthermore, we allow the client to
- // pass in custom memory allocator/deallocator routines.
- //--------------------------------------------------------------
- struct Object {
- Object* next;
- // The real data starts here
- };
-
- Allocator alloc_; // The allocator
- DeAllocator dealloc_; // The deallocator
- Object* allocated_; // List of allocated objects
-
- // Allocates a zeroed array of T with length "num". Also inserts
- // the allocated block into a linked list so it can be deallocated
- // when we are all done.
- template <class T> T* New(int num) {
- void* ptr = (*alloc_)(sizeof(Object) + num*sizeof(T));
- memset(ptr, 0, sizeof(Object) + num*sizeof(T));
- Object* obj = reinterpret_cast<Object*>(ptr);
- obj->next = allocated_;
- allocated_ = obj;
- return reinterpret_cast<T*>(reinterpret_cast<Object*>(ptr) + 1);
- }
-};
-
-// More implementation details follow:
-
-template <class Value>
-AddressMap<Value>::AddressMap(Allocator alloc, DeAllocator dealloc)
- : free_(NULL),
- alloc_(alloc),
- dealloc_(dealloc),
- allocated_(NULL) {
- hashtable_ = New<Cluster*>(kHashSize);
-}
-
-template <class Value>
-AddressMap<Value>::~AddressMap() {
- // De-allocate all of the objects we allocated
- for (Object* obj = allocated_; obj != NULL; /**/) {
- Object* next = obj->next;
- (*dealloc_)(obj);
- obj = next;
- }
-}
-
-template <class Value>
-inline const Value* AddressMap<Value>::Find(Key key) const {
- return const_cast<AddressMap*>(this)->FindMutable(key);
-}
-
-template <class Value>
-inline Value* AddressMap<Value>::FindMutable(Key key) {
- const Number num = reinterpret_cast<Number>(key);
- const Cluster* const c = FindCluster(num, false/*do not create*/);
- if (c != NULL) {
- for (Entry* e = c->blocks[BlockID(num)]; e != NULL; e = e->next) {
- if (e->key == key) {
- return &e->value;
- }
- }
- }
- return NULL;
-}
-
-template <class Value>
-void AddressMap<Value>::Insert(Key key, Value value) {
- const Number num = reinterpret_cast<Number>(key);
- Cluster* const c = FindCluster(num, true/*create*/);
-
- // Look in linked-list for this block
- const int block = BlockID(num);
- for (Entry* e = c->blocks[block]; e != NULL; e = e->next) {
- if (e->key == key) {
- e->value = value;
- return;
- }
- }
-
- // Create entry
- if (free_ == NULL) {
- // Allocate a new batch of entries and add to free-list
- Entry* array = New<Entry>(ALLOC_COUNT);
- for (int i = 0; i < ALLOC_COUNT-1; i++) {
- array[i].next = &array[i+1];
- }
- array[ALLOC_COUNT-1].next = free_;
- free_ = &array[0];
- }
- Entry* e = free_;
- free_ = e->next;
- e->key = key;
- e->value = value;
- e->next = c->blocks[block];
- c->blocks[block] = e;
-}
-
-template <class Value>
-bool AddressMap<Value>::FindAndRemove(Key key, Value* removed_value) {
- const Number num = reinterpret_cast<Number>(key);
- Cluster* const c = FindCluster(num, false/*do not create*/);
- if (c != NULL) {
- for (Entry** p = &c->blocks[BlockID(num)]; *p != NULL; p = &(*p)->next) {
- Entry* e = *p;
- if (e->key == key) {
- *removed_value = e->value;
- *p = e->next; // Remove e from linked-list
- e->next = free_; // Add e to free-list
- free_ = e;
- return true;
- }
- }
- }
- return false;
-}
-
-template <class Value>
-const Value* AddressMap<Value>::FindInside(ValueSizeFunc size_func,
- size_t max_size,
- Key key,
- Key* res_key) {
- const Number key_num = reinterpret_cast<Number>(key);
- Number num = key_num; // we'll move this to move back through the clusters
- while (1) {
- const Cluster* c = FindCluster(num, false/*do not create*/);
- if (c != NULL) {
- while (1) {
- const int block = BlockID(num);
- bool had_smaller_key = false;
- for (const Entry* e = c->blocks[block]; e != NULL; e = e->next) {
- const Number e_num = reinterpret_cast<Number>(e->key);
- if (e_num <= key_num) {
- if (e_num == key_num || // to handle 0-sized ranges
- key_num < e_num + (*size_func)(e->value)) {
- *res_key = e->key;
- return &e->value;
- }
- had_smaller_key = true;
- }
- }
- if (had_smaller_key) return NULL; // got a range before 'key'
- // and it did not contain 'key'
- if (block == 0) break;
- // try address-wise previous block
- num |= kBlockSize - 1; // start at the last addr of prev block
- num -= kBlockSize;
- if (key_num - num > max_size) return NULL;
- }
- }
- if (num < kClusterSize) return NULL; // first cluster
- // go to address-wise previous cluster to try
- num |= kClusterSize - 1; // start at the last block of previous cluster
- num -= kClusterSize;
- if (key_num - num > max_size) return NULL;
- // Having max_size to limit the search is crucial: else
- // we have to traverse a lot of empty clusters (or blocks).
- // We can avoid needing max_size if we put clusters into
- // a search tree, but performance suffers considerably
- // if we use this approach by using stl::set.
- }
-}
-
-template <class Value>
-template <class Type>
-inline void AddressMap<Value>::Iterate(void (*callback)(Key, Value*, Type),
- Type arg) const {
- // We could optimize this by traversing only non-empty clusters and/or blocks
- // but it does not speed up heap-checker noticeably.
- for (int h = 0; h < kHashSize; ++h) {
- for (const Cluster* c = hashtable_[h]; c != NULL; c = c->next) {
- for (int b = 0; b < kClusterBlocks; ++b) {
- for (Entry* e = c->blocks[b]; e != NULL; e = e->next) {
- callback(e->key, &e->value, arg);
- }
- }
- }
- }
-}
-
-#endif // BASE_ADDRESSMAP_INL_H_
diff --git a/src/third_party/gperftools-2.5/src/base/arm_instruction_set_select.h b/src/third_party/gperftools-2.5/src/base/arm_instruction_set_select.h
deleted file mode 100644
index 6fde685272c..00000000000
--- a/src/third_party/gperftools-2.5/src/base/arm_instruction_set_select.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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: Alexander Levitskiy
-//
-// Generalizes the plethora of ARM flavors available to an easier to manage set
-// Defs reference is at https://wiki.edubuntu.org/ARM/Thumb2PortingHowto
-
-#ifndef ARM_INSTRUCTION_SET_SELECT_H_
-#define ARM_INSTRUCTION_SET_SELECT_H_
-
-#if defined(__ARM_ARCH_8A__)
-# define ARMV8 1
-#endif
-
-#if defined(ARMV8) || \
- defined(__ARM_ARCH_7__) || \
- defined(__ARM_ARCH_7R__) || \
- defined(__ARM_ARCH_7A__)
-# define ARMV7 1
-#endif
-
-#if defined(ARMV7) || \
- defined(__ARM_ARCH_6__) || \
- defined(__ARM_ARCH_6J__) || \
- defined(__ARM_ARCH_6K__) || \
- defined(__ARM_ARCH_6Z__) || \
- defined(__ARM_ARCH_6T2__) || \
- defined(__ARM_ARCH_6ZK__)
-# define ARMV6 1
-#endif
-
-#if defined(ARMV6) || \
- defined(__ARM_ARCH_5T__) || \
- defined(__ARM_ARCH_5E__) || \
- defined(__ARM_ARCH_5TE__) || \
- defined(__ARM_ARCH_5TEJ__)
-# define ARMV5 1
-#endif
-
-#if defined(ARMV5) || \
- defined(__ARM_ARCH_4__) || \
- defined(__ARM_ARCH_4T__)
-# define ARMV4 1
-#endif
-
-#if defined(ARMV4) || \
- defined(__ARM_ARCH_3__) || \
- defined(__ARM_ARCH_3M__)
-# define ARMV3 1
-#endif
-
-#if defined(ARMV3) || \
- defined(__ARM_ARCH_2__)
-# define ARMV2 1
-#endif
-
-#endif // ARM_INSTRUCTION_SET_SELECT_H_
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops-internals-arm-generic.h b/src/third_party/gperftools-2.5/src/base/atomicops-internals-arm-generic.h
deleted file mode 100644
index d0f941309bb..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops-internals-arm-generic.h
+++ /dev/null
@@ -1,228 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2003, 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: Lei Zhang, Sasha Levitskiy
-//
-// This file is an internal atomic implementation, use base/atomicops.h instead.
-//
-// LinuxKernelCmpxchg is from Google Gears.
-
-#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_
-#define BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "base/basictypes.h"
-
-typedef int32_t Atomic32;
-
-namespace base {
-namespace subtle {
-
-typedef int64_t Atomic64;
-
-// 0xffff0fc0 is the hard coded address of a function provided by
-// the kernel which implements an atomic compare-exchange. On older
-// ARM architecture revisions (pre-v6) this may be implemented using
-// a syscall. This address is stable, and in active use (hard coded)
-// by at least glibc-2.7 and the Android C library.
-// pLinuxKernelCmpxchg has both acquire and release barrier sematincs.
-typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value,
- Atomic32 new_value,
- volatile Atomic32* ptr);
-LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg ATTRIBUTE_WEAK =
- (LinuxKernelCmpxchgFunc) 0xffff0fc0;
-
-typedef void (*LinuxKernelMemoryBarrierFunc)(void);
-LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier ATTRIBUTE_WEAK =
- (LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
-
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev_value = *ptr;
- do {
- if (!pLinuxKernelCmpxchg(old_value, new_value,
- const_cast<Atomic32*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- Atomic32 old_value;
- do {
- old_value = *ptr;
- } while (pLinuxKernelCmpxchg(old_value, new_value,
- const_cast<Atomic32*>(ptr)));
- return old_value;
-}
-
-inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- // pLinuxKernelCmpxchg already has acquire and release barrier semantics.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- // pLinuxKernelCmpxchg already has acquire and release barrier semantics.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
-}
-
-inline void MemoryBarrier() {
- pLinuxKernelMemoryBarrier();
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
- MemoryBarrier();
- *ptr = value;
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
- return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
- Atomic32 value = *ptr;
- MemoryBarrier();
- return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-
-// 64-bit versions are not implemented yet.
-
-inline void NotImplementedFatalError(const char *function_name) {
- fprintf(stderr, "64-bit %s() not implemented on this platform\n",
- function_name);
- abort();
-}
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- NotImplementedFatalError("NoBarrier_CompareAndSwap");
- return 0;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- NotImplementedFatalError("NoBarrier_AtomicExchange");
- return 0;
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- // pLinuxKernelCmpxchg already has acquire and release barrier semantics.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- // pLinuxKernelCmpxchg already has acquire and release barrier semantics.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- NotImplementedFatalError("NoBarrier_Store");
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NotImplementedFatalError("Acquire_Store64");
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
- NotImplementedFatalError("Release_Store");
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- NotImplementedFatalError("NoBarrier_Load");
- return 0;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
- NotImplementedFatalError("Atomic64 Acquire_Load");
- return 0;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- NotImplementedFatalError("Atomic64 Release_Load");
- return 0;
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- NotImplementedFatalError("Atomic64 Acquire_CompareAndSwap");
- return 0;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- NotImplementedFatalError("Atomic64 Release_CompareAndSwap");
- return 0;
-}
-
-} // namespace base::subtle
-} // namespace base
-
-#endif // BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops-internals-arm-v6plus.h b/src/third_party/gperftools-2.5/src/base/atomicops-internals-arm-v6plus.h
deleted file mode 100644
index 35f10481b04..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops-internals-arm-v6plus.h
+++ /dev/null
@@ -1,330 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sasha Levitskiy
-// based on atomicops-internals by Sanjay Ghemawat
-//
-// This file is an internal atomic implementation, use base/atomicops.h instead.
-//
-// This code implements ARM atomics for architectures V6 and newer.
-
-#ifndef BASE_ATOMICOPS_INTERNALS_ARM_V6PLUS_H_
-#define BASE_ATOMICOPS_INTERNALS_ARM_V6PLUS_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "base/basictypes.h" // For COMPILE_ASSERT
-
-// The LDREXD and STREXD instructions in ARM all v7 variants or above. In v6,
-// only some variants support it. For simplicity, we only use exclusive
-// 64-bit load/store in V7 or above.
-#if defined(ARMV7)
-# define BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
-#endif
-
-typedef int32_t Atomic32;
-
-namespace base {
-namespace subtle {
-
-typedef int64_t Atomic64;
-
-// 32-bit low-level ops
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 oldval, res;
- do {
- __asm__ __volatile__(
- "ldrex %1, [%3]\n"
- "mov %0, #0\n"
- "teq %1, %4\n"
- // The following IT (if-then) instruction is needed for the subsequent
- // conditional instruction STREXEQ when compiling in THUMB mode.
- // In ARM mode, the compiler/assembler will not generate any code for it.
- "it eq\n"
- "strexeq %0, %5, [%3]\n"
- : "=&r" (res), "=&r" (oldval), "+Qo" (*ptr)
- : "r" (ptr), "Ir" (old_value), "r" (new_value)
- : "cc");
- } while (res);
- return oldval;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- Atomic32 tmp, old;
- __asm__ __volatile__(
- "1:\n"
- "ldrex %1, [%2]\n"
- "strex %0, %3, [%2]\n"
- "teq %0, #0\n"
- "bne 1b"
- : "=&r" (tmp), "=&r" (old)
- : "r" (ptr), "r" (new_value)
- : "cc", "memory");
- return old;
-}
-
-inline void MemoryBarrier() {
-#if !defined(ARMV7)
- uint32_t dest = 0;
- __asm__ __volatile__("mcr p15,0,%0,c7,c10,5" :"=&r"(dest) : : "memory");
-#else
- __asm__ __volatile__("dmb" : : : "memory");
-#endif
-}
-
-inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- Atomic32 old_value = NoBarrier_AtomicExchange(ptr, new_value);
- MemoryBarrier();
- return old_value;
-}
-
-inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- MemoryBarrier();
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 value = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
- MemoryBarrier();
- return value;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- MemoryBarrier();
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
- MemoryBarrier();
- *ptr = value;
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
- return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
- Atomic32 value = *ptr;
- MemoryBarrier();
- return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-// 64-bit versions are only available if LDREXD and STREXD instructions
-// are available.
-#ifdef BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
-
-#define BASE_HAS_ATOMIC64 1
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 oldval, res;
- do {
- __asm__ __volatile__(
- "ldrexd %1, [%3]\n"
- "mov %0, #0\n"
- "teq %Q1, %Q4\n"
- // The following IT (if-then) instructions are needed for the subsequent
- // conditional instructions when compiling in THUMB mode.
- // In ARM mode, the compiler/assembler will not generate any code for it.
- "it eq\n"
- "teqeq %R1, %R4\n"
- "it eq\n"
- "strexdeq %0, %5, [%3]\n"
- : "=&r" (res), "=&r" (oldval), "+Q" (*ptr)
- : "r" (ptr), "Ir" (old_value), "r" (new_value)
- : "cc");
- } while (res);
- return oldval;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- int store_failed;
- Atomic64 old;
- __asm__ __volatile__(
- "1:\n"
- "ldrexd %1, [%2]\n"
- "strexd %0, %3, [%2]\n"
- "teq %0, #0\n"
- "bne 1b"
- : "=&r" (store_failed), "=&r" (old)
- : "r" (ptr), "r" (new_value)
- : "cc", "memory");
- return old;
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- Atomic64 old_value = NoBarrier_AtomicExchange(ptr, new_value);
- MemoryBarrier();
- return old_value;
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- MemoryBarrier();
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- int store_failed;
- Atomic64 dummy;
- __asm__ __volatile__(
- "1:\n"
- // Dummy load to lock cache line.
- "ldrexd %1, [%3]\n"
- "strexd %0, %2, [%3]\n"
- "teq %0, #0\n"
- "bne 1b"
- : "=&r" (store_failed), "=&r"(dummy)
- : "r"(value), "r" (ptr)
- : "cc", "memory");
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- Atomic64 res;
- __asm__ __volatile__(
- "ldrexd %0, [%1]\n"
- "clrex\n"
- : "=r" (res)
- : "r"(ptr), "Q"(*ptr));
- return res;
-}
-
-#else // BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
-
-inline void NotImplementedFatalError(const char *function_name) {
- fprintf(stderr, "64-bit %s() not implemented on this platform\n",
- function_name);
- abort();
-}
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- NotImplementedFatalError("NoBarrier_CompareAndSwap");
- return 0;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- NotImplementedFatalError("NoBarrier_AtomicExchange");
- return 0;
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- NotImplementedFatalError("Acquire_AtomicExchange");
- return 0;
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- NotImplementedFatalError("Release_AtomicExchange");
- return 0;
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- NotImplementedFatalError("NoBarrier_Store");
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- NotImplementedFatalError("NoBarrier_Load");
- return 0;
-}
-
-#endif // BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NoBarrier_Store(ptr, value);
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
- MemoryBarrier();
- NoBarrier_Store(ptr, value);
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
- Atomic64 value = NoBarrier_Load(ptr);
- MemoryBarrier();
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return NoBarrier_Load(ptr);
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 value = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
- MemoryBarrier();
- return value;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- MemoryBarrier();
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-} // namespace subtle ends
-} // namespace base ends
-
-#endif // BASE_ATOMICOPS_INTERNALS_ARM_V6PLUS_H_
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops-internals-gcc.h b/src/third_party/gperftools-2.5/src/base/atomicops-internals-gcc.h
deleted file mode 100644
index f8d27863cb7..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops-internals-gcc.h
+++ /dev/null
@@ -1,203 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2014, Linaro
-// 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: Riku Voipio, riku.voipio@linaro.org
-//
-// atomic primitives implemented with gcc atomic intrinsics:
-// http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
-//
-
-#ifndef BASE_ATOMICOPS_INTERNALS_GCC_GENERIC_H_
-#define BASE_ATOMICOPS_INTERNALS_GCC_GENERIC_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "base/basictypes.h"
-
-typedef int32_t Atomic32;
-
-namespace base {
-namespace subtle {
-
-typedef int64_t Atomic64;
-
-inline void MemoryBarrier() {
- __sync_synchronize();
-}
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
- 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
- return prev_value;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- return __atomic_exchange_n(const_cast<Atomic32*>(ptr), new_value, __ATOMIC_RELAXED);
-}
-
-inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- return __atomic_exchange_n(const_cast<Atomic32*>(ptr), new_value, __ATOMIC_ACQUIRE);
-}
-
-inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- return __atomic_exchange_n(const_cast<Atomic32*>(ptr), new_value, __ATOMIC_RELEASE);
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
- 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
- return prev_value;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
- 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
- return prev_value;
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
- MemoryBarrier();
- *ptr = value;
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
- return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
- Atomic32 value = *ptr;
- MemoryBarrier();
- return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-// 64-bit versions
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
- 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
- return prev_value;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- return __atomic_exchange_n(const_cast<Atomic64*>(ptr), new_value, __ATOMIC_RELAXED);
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- return __atomic_exchange_n(const_cast<Atomic64*>(ptr), new_value, __ATOMIC_ACQUIRE);
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- return __atomic_exchange_n(const_cast<Atomic64*>(ptr), new_value, __ATOMIC_RELEASE);
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
- 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
- return prev_value;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev_value = old_value;
- __atomic_compare_exchange_n(ptr, &prev_value, new_value,
- 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
- return prev_value;
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
- MemoryBarrier();
- *ptr = value;
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
- Atomic64 value = *ptr;
- MemoryBarrier();
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-} // namespace base::subtle
-} // namespace base
-
-#endif // BASE_ATOMICOPS_INTERNALS_GCC_GENERIC_H_
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops-internals-linuxppc.h b/src/third_party/gperftools-2.5/src/base/atomicops-internals-linuxppc.h
deleted file mode 100644
index b52fdf0d1ec..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops-internals-linuxppc.h
+++ /dev/null
@@ -1,437 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* 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.
- *
- * ---
- */
-
-// Implementation of atomic operations for ppc-linux. This file should not
-// be included directly. Clients should instead include
-// "base/atomicops.h".
-
-#ifndef BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
-#define BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
-
-typedef int32_t Atomic32;
-
-#ifdef __PPC64__
-#define BASE_HAS_ATOMIC64 1
-#endif
-
-namespace base {
-namespace subtle {
-
-static inline void _sync(void) {
- __asm__ __volatile__("sync": : : "memory");
-}
-
-static inline void _lwsync(void) {
- // gcc defines __NO_LWSYNC__ when appropriate; see
- // http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01238.html
-#ifdef __NO_LWSYNC__
- __asm__ __volatile__("msync": : : "memory");
-#else
- __asm__ __volatile__("lwsync": : : "memory");
-#endif
-}
-
-static inline void _isync(void) {
- __asm__ __volatile__("isync": : : "memory");
-}
-
-static inline Atomic32 OSAtomicAdd32(Atomic32 amount, Atomic32 *value) {
- Atomic32 t;
- __asm__ __volatile__(
-"1: lwarx %0,0,%3\n\
- add %0,%2,%0\n\
- stwcx. %0,0,%3 \n\
- bne- 1b"
- : "=&r" (t), "+m" (*value)
- : "r" (amount), "r" (value)
- : "cc");
- return t;
-}
-
-static inline Atomic32 OSAtomicAdd32Barrier(Atomic32 amount, Atomic32 *value) {
- Atomic32 t;
- _lwsync();
- t = OSAtomicAdd32(amount, value);
- // This is based on the code snippet in the architecture manual (Vol
- // 2, Appendix B). It's a little tricky: correctness depends on the
- // fact that the code right before this (in OSAtomicAdd32) has a
- // conditional branch with a data dependency on the update.
- // Otherwise, we'd have to use sync.
- _isync();
- return t;
-}
-
-static inline bool OSAtomicCompareAndSwap32(Atomic32 old_value,
- Atomic32 new_value,
- Atomic32 *value) {
- Atomic32 prev;
- __asm__ __volatile__(
-"1: lwarx %0,0,%2\n\
- cmpw 0,%0,%3\n\
- bne- 2f\n\
- stwcx. %4,0,%2\n\
- bne- 1b\n\
-2:"
- : "=&r" (prev), "+m" (*value)
- : "r" (value), "r" (old_value), "r" (new_value)
- : "cc");
- return prev == old_value;
-}
-
-static inline Atomic32 OSAtomicCompareAndSwap32Acquire(Atomic32 old_value,
- Atomic32 new_value,
- Atomic32 *value) {
- Atomic32 t;
- t = OSAtomicCompareAndSwap32(old_value, new_value, value);
- // This is based on the code snippet in the architecture manual (Vol
- // 2, Appendix B). It's a little tricky: correctness depends on the
- // fact that the code right before this (in
- // OSAtomicCompareAndSwap32) has a conditional branch with a data
- // dependency on the update. Otherwise, we'd have to use sync.
- _isync();
- return t;
-}
-
-static inline Atomic32 OSAtomicCompareAndSwap32Release(Atomic32 old_value,
- Atomic32 new_value,
- Atomic32 *value) {
- _lwsync();
- return OSAtomicCompareAndSwap32(old_value, new_value, value);
-}
-
-typedef int64_t Atomic64;
-
-inline void MemoryBarrier() {
- // This can't be _lwsync(); we need to order the immediately
- // preceding stores against any load that may follow, but lwsync
- // doesn't guarantee that.
- _sync();
-}
-
-// 32-bit Versions.
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev_value;
- do {
- if (OSAtomicCompareAndSwap32(old_value, new_value,
- const_cast<Atomic32*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
- Atomic32 new_value) {
- Atomic32 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap32(old_value, new_value,
- const_cast<Atomic32*>(ptr)));
- return old_value;
-}
-
-inline Atomic32 Acquire_AtomicExchange(volatile Atomic32 *ptr,
- Atomic32 new_value) {
- Atomic32 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap32Acquire(old_value, new_value,
- const_cast<Atomic32*>(ptr)));
- return old_value;
-}
-
-inline Atomic32 Release_AtomicExchange(volatile Atomic32 *ptr,
- Atomic32 new_value) {
- Atomic32 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap32Release(old_value, new_value,
- const_cast<Atomic32*>(ptr)));
- return old_value;
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev_value;
- do {
- if (OSAtomicCompareAndSwap32Acquire(old_value, new_value,
- const_cast<Atomic32*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev_value;
- do {
- if (OSAtomicCompareAndSwap32Release(old_value, new_value,
- const_cast<Atomic32*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-#ifdef __PPC64__
-
-// 64-bit Versions.
-
-static inline Atomic64 OSAtomicAdd64(Atomic64 amount, Atomic64 *value) {
- Atomic64 t;
- __asm__ __volatile__(
-"1: ldarx %0,0,%3\n\
- add %0,%2,%0\n\
- stdcx. %0,0,%3 \n\
- bne- 1b"
- : "=&r" (t), "+m" (*value)
- : "r" (amount), "r" (value)
- : "cc");
- return t;
-}
-
-static inline Atomic64 OSAtomicAdd64Barrier(Atomic64 amount, Atomic64 *value) {
- Atomic64 t;
- _lwsync();
- t = OSAtomicAdd64(amount, value);
- // This is based on the code snippet in the architecture manual (Vol
- // 2, Appendix B). It's a little tricky: correctness depends on the
- // fact that the code right before this (in OSAtomicAdd64) has a
- // conditional branch with a data dependency on the update.
- // Otherwise, we'd have to use sync.
- _isync();
- return t;
-}
-
-static inline bool OSAtomicCompareAndSwap64(Atomic64 old_value,
- Atomic64 new_value,
- Atomic64 *value) {
- Atomic64 prev;
- __asm__ __volatile__(
-"1: ldarx %0,0,%2\n\
- cmpd 0,%0,%3\n\
- bne- 2f\n\
- stdcx. %4,0,%2\n\
- bne- 1b\n\
-2:"
- : "=&r" (prev), "+m" (*value)
- : "r" (value), "r" (old_value), "r" (new_value)
- : "cc");
- return prev == old_value;
-}
-
-static inline Atomic64 OSAtomicCompareAndSwap64Acquire(Atomic64 old_value,
- Atomic64 new_value,
- Atomic64 *value) {
- Atomic64 t;
- t = OSAtomicCompareAndSwap64(old_value, new_value, value);
- // This is based on the code snippet in the architecture manual (Vol
- // 2, Appendix B). It's a little tricky: correctness depends on the
- // fact that the code right before this (in
- // OSAtomicCompareAndSwap64) has a conditional branch with a data
- // dependency on the update. Otherwise, we'd have to use sync.
- _isync();
- return t;
-}
-
-static inline Atomic64 OSAtomicCompareAndSwap64Release(Atomic64 old_value,
- Atomic64 new_value,
- Atomic64 *value) {
- _lwsync();
- return OSAtomicCompareAndSwap64(old_value, new_value, value);
-}
-
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev_value;
- do {
- if (OSAtomicCompareAndSwap64(old_value, new_value,
- const_cast<Atomic64*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
- Atomic64 new_value) {
- Atomic64 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap64(old_value, new_value,
- const_cast<Atomic64*>(ptr)));
- return old_value;
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64 *ptr,
- Atomic64 new_value) {
- Atomic64 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap64Acquire(old_value, new_value,
- const_cast<Atomic64*>(ptr)));
- return old_value;
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64 *ptr,
- Atomic64 new_value) {
- Atomic64 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap64Release(old_value, new_value,
- const_cast<Atomic64*>(ptr)));
- return old_value;
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev_value;
- do {
- if (OSAtomicCompareAndSwap64Acquire(old_value, new_value,
- const_cast<Atomic64*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev_value;
- do {
- if (OSAtomicCompareAndSwap64Release(old_value, new_value,
- const_cast<Atomic64*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-#endif
-
-inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
- *ptr = value;
- // This can't be _lwsync(); we need to order the immediately
- // preceding stores against any load that may follow, but lwsync
- // doesn't guarantee that.
- _sync();
-}
-
-inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
- _lwsync();
- *ptr = value;
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) {
- return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
- Atomic32 value = *ptr;
- _lwsync();
- return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
- // This can't be _lwsync(); we need to order the immediately
- // preceding stores against any load that may follow, but lwsync
- // doesn't guarantee that.
- _sync();
- return *ptr;
-}
-
-#ifdef __PPC64__
-
-// 64-bit Versions.
-
-inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
- *ptr = value;
- // This can't be _lwsync(); we need to order the immediately
- // preceding stores against any load that may follow, but lwsync
- // doesn't guarantee that.
- _sync();
-}
-
-inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
- _lwsync();
- *ptr = value;
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64 *ptr) {
- return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
- Atomic64 value = *ptr;
- _lwsync();
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
- // This can't be _lwsync(); we need to order the immediately
- // preceding stores against any load that may follow, but lwsync
- // doesn't guarantee that.
- _sync();
- return *ptr;
-}
-
-#endif
-
-} // namespace base::subtle
-} // namespace base
-
-#endif // BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops-internals-macosx.h b/src/third_party/gperftools-2.5/src/base/atomicops-internals-macosx.h
deleted file mode 100644
index b5130d4f4d7..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops-internals-macosx.h
+++ /dev/null
@@ -1,370 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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.
- */
-
-// Implementation of atomic operations for Mac OS X. This file should not
-// be included directly. Clients should instead include
-// "base/atomicops.h".
-
-#ifndef BASE_ATOMICOPS_INTERNALS_MACOSX_H_
-#define BASE_ATOMICOPS_INTERNALS_MACOSX_H_
-
-typedef int32_t Atomic32;
-
-// MacOS uses long for intptr_t, AtomicWord and Atomic32 are always different
-// on the Mac, even when they are the same size. Similarly, on __ppc64__,
-// AtomicWord and Atomic64 are always different. Thus, we need explicit
-// casting.
-#ifdef __LP64__
-#define AtomicWordCastType base::subtle::Atomic64
-#else
-#define AtomicWordCastType Atomic32
-#endif
-
-#if defined(__LP64__) || defined(__i386__)
-#define BASE_HAS_ATOMIC64 1 // Use only in tests and base/atomic*
-#endif
-
-#include <libkern/OSAtomic.h>
-
-namespace base {
-namespace subtle {
-
-#if !defined(__LP64__) && defined(__ppc__)
-
-// The Mac 64-bit OSAtomic implementations are not available for 32-bit PowerPC,
-// while the underlying assembly instructions are available only some
-// implementations of PowerPC.
-
-// The following inline functions will fail with the error message at compile
-// time ONLY IF they are called. So it is safe to use this header if user
-// code only calls AtomicWord and Atomic32 operations.
-//
-// NOTE(vchen): Implementation notes to implement the atomic ops below may
-// be found in "PowerPC Virtual Environment Architecture, Book II,
-// Version 2.02", January 28, 2005, Appendix B, page 46. Unfortunately,
-// extra care must be taken to ensure data are properly 8-byte aligned, and
-// that data are returned correctly according to Mac OS X ABI specs.
-
-inline int64_t OSAtomicCompareAndSwap64(
- int64_t oldValue, int64_t newValue, int64_t *theValue) {
- __asm__ __volatile__(
- "_OSAtomicCompareAndSwap64_not_supported_for_32_bit_ppc\n\t");
- return 0;
-}
-
-inline int64_t OSAtomicAdd64(int64_t theAmount, int64_t *theValue) {
- __asm__ __volatile__(
- "_OSAtomicAdd64_not_supported_for_32_bit_ppc\n\t");
- return 0;
-}
-
-inline int64_t OSAtomicCompareAndSwap64Barrier(
- int64_t oldValue, int64_t newValue, int64_t *theValue) {
- int64_t prev = OSAtomicCompareAndSwap64(oldValue, newValue, theValue);
- OSMemoryBarrier();
- return prev;
-}
-
-inline int64_t OSAtomicAdd64Barrier(
- int64_t theAmount, int64_t *theValue) {
- int64_t new_val = OSAtomicAdd64(theAmount, theValue);
- OSMemoryBarrier();
- return new_val;
-}
-#endif
-
-typedef int64_t Atomic64;
-
-inline void MemoryBarrier() {
- OSMemoryBarrier();
-}
-
-// 32-bit Versions.
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev_value;
- do {
- if (OSAtomicCompareAndSwap32(old_value, new_value,
- const_cast<Atomic32*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
- Atomic32 new_value) {
- Atomic32 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap32(old_value, new_value,
- const_cast<Atomic32*>(ptr)));
- return old_value;
-}
-
-inline Atomic32 Acquire_AtomicExchange(volatile Atomic32 *ptr,
- Atomic32 new_value) {
- Atomic32 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap32Barrier(old_value, new_value,
- const_cast<Atomic32*>(ptr)));
- return old_value;
-}
-
-inline Atomic32 Release_AtomicExchange(volatile Atomic32 *ptr,
- Atomic32 new_value) {
- return Acquire_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev_value;
- do {
- if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
- const_cast<Atomic32*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- return Acquire_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
- MemoryBarrier();
- *ptr = value;
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
- return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
- Atomic32 value = *ptr;
- MemoryBarrier();
- return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-// 64-bit version
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev_value;
- do {
- if (OSAtomicCompareAndSwap64(old_value, new_value,
- const_cast<Atomic64*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
- Atomic64 new_value) {
- Atomic64 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap64(old_value, new_value,
- const_cast<Atomic64*>(ptr)));
- return old_value;
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64 *ptr,
- Atomic64 new_value) {
- Atomic64 old_value;
- do {
- old_value = *ptr;
- } while (!OSAtomicCompareAndSwap64Barrier(old_value, new_value,
- const_cast<Atomic64*>(ptr)));
- return old_value;
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64 *ptr,
- Atomic64 new_value) {
- return Acquire_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev_value;
- do {
- if (OSAtomicCompareAndSwap64Barrier(old_value, new_value,
- const_cast<Atomic64*>(ptr))) {
- return old_value;
- }
- prev_value = *ptr;
- } while (prev_value == old_value);
- return prev_value;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- // The lib kern interface does not distinguish between
- // Acquire and Release memory barriers; they are equivalent.
- return Acquire_CompareAndSwap(ptr, old_value, new_value);
-}
-
-#ifdef __LP64__
-
-// 64-bit implementation on 64-bit platform
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
- MemoryBarrier();
- *ptr = value;
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
- Atomic64 value = *ptr;
- MemoryBarrier();
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-#else
-
-// 64-bit implementation on 32-bit platform
-
-#if defined(__ppc__)
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- __asm__ __volatile__(
- "_NoBarrier_Store_not_supported_for_32_bit_ppc\n\t");
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- __asm__ __volatile__(
- "_NoBarrier_Load_not_supported_for_32_bit_ppc\n\t");
- return 0;
-}
-
-#elif defined(__i386__)
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- __asm__ __volatile__("movq %1, %%mm0\n\t" // Use mmx reg for 64-bit atomic
- "movq %%mm0, %0\n\t" // moves (ptr could be read-only)
- "emms\n\t" // Reset FP registers
- : "=m" (*ptr)
- : "m" (value)
- : // mark the FP stack and mmx registers as clobbered
- "st", "st(1)", "st(2)", "st(3)", "st(4)",
- "st(5)", "st(6)", "st(7)", "mm0", "mm1",
- "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
-
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- Atomic64 value;
- __asm__ __volatile__("movq %1, %%mm0\n\t" // Use mmx reg for 64-bit atomic
- "movq %%mm0, %0\n\t" // moves (ptr could be read-only)
- "emms\n\t" // Reset FP registers
- : "=m" (value)
- : "m" (*ptr)
- : // mark the FP stack and mmx registers as clobbered
- "st", "st(1)", "st(2)", "st(3)", "st(4)",
- "st(5)", "st(6)", "st(7)", "mm0", "mm1",
- "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
-
- return value;
-}
-#endif
-
-
-inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
- NoBarrier_Store(ptr, value);
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
- MemoryBarrier();
- NoBarrier_Store(ptr, value);
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
- Atomic64 value = NoBarrier_Load(ptr);
- MemoryBarrier();
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
- MemoryBarrier();
- return NoBarrier_Load(ptr);
-}
-#endif // __LP64__
-
-} // namespace base::subtle
-} // namespace base
-
-#endif // BASE_ATOMICOPS_INTERNALS_MACOSX_H_
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops-internals-mips.h b/src/third_party/gperftools-2.5/src/base/atomicops-internals-mips.h
deleted file mode 100644
index 4bfd7f6c70d..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops-internals-mips.h
+++ /dev/null
@@ -1,323 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2013, 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: Jovan Zelincevic <jovan.zelincevic@imgtec.com>
-// based on atomicops-internals by Sanjay Ghemawat
-
-// This file is an internal atomic implementation, use base/atomicops.h instead.
-//
-// This code implements MIPS atomics.
-
-#ifndef BASE_ATOMICOPS_INTERNALS_MIPS_H_
-#define BASE_ATOMICOPS_INTERNALS_MIPS_H_
-
-#if (_MIPS_ISA == _MIPS_ISA_MIPS64)
-#define BASE_HAS_ATOMIC64 1
-#endif
-
-typedef int32_t Atomic32;
-
-namespace base {
-namespace subtle {
-
-// Atomically execute:
-// result = *ptr;
-// if (*ptr == old_value)
-// *ptr = new_value;
-// return result;
-//
-// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
-// Always return the old value of "*ptr"
-//
-// This routine implies no memory barriers.
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value)
-{
- Atomic32 prev, tmp;
- __asm__ volatile(
- ".set push \n"
- ".set noreorder \n"
-
- "1: \n"
- "ll %0, %5 \n" // prev = *ptr
- "bne %0, %3, 2f \n" // if (prev != old_value) goto 2
- " move %2, %4 \n" // tmp = new_value
- "sc %2, %1 \n" // *ptr = tmp (with atomic check)
- "beqz %2, 1b \n" // start again on atomic error
- " nop \n" // delay slot nop
- "2: \n"
-
- ".set pop \n"
- : "=&r" (prev), "=m" (*ptr),
- "=&r" (tmp)
- : "Ir" (old_value), "r" (new_value),
- "m" (*ptr)
- : "memory"
- );
- return prev;
-}
-
-// Atomically store new_value into *ptr, returning the previous value held in
-// *ptr. This routine implies no memory barriers.
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value)
-{
- Atomic32 temp, old;
- __asm__ volatile(
- ".set push \n"
- ".set noreorder \n"
-
- "1: \n"
- "ll %1, %2 \n" // old = *ptr
- "move %0, %3 \n" // temp = new_value
- "sc %0, %2 \n" // *ptr = temp (with atomic check)
- "beqz %0, 1b \n" // start again on atomic error
- " nop \n" // delay slot nop
-
- ".set pop \n"
- : "=&r" (temp), "=&r" (old),
- "=m" (*ptr)
- : "r" (new_value), "m" (*ptr)
- : "memory"
- );
- return old;
-}
-
-inline void MemoryBarrier()
-{
- __asm__ volatile("sync" : : : "memory");
-}
-
-// "Acquire" operations
-// ensure that no later memory access can be reordered ahead of the operation.
-// "Release" operations ensure that no previous memory access can be reordered
-// after the operation. "Barrier" operations have both "Acquire" and "Release"
-// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
-// access.
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value)
-{
- Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
- MemoryBarrier();
- return res;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value)
-{
- MemoryBarrier();
- Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
- return res;
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value)
-{
- *ptr = value;
-}
-
-inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value)
-{
- Atomic32 old_value = NoBarrier_AtomicExchange(ptr, new_value);
- MemoryBarrier();
- return old_value;
-}
-
-inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value)
-{
- MemoryBarrier();
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value)
-{
- *ptr = value;
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value)
-{
- MemoryBarrier();
- *ptr = value;
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr)
-{
- return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr)
-{
- Atomic32 value = *ptr;
- MemoryBarrier();
- return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr)
-{
- MemoryBarrier();
- return *ptr;
-}
-
-#if (_MIPS_ISA == _MIPS_ISA_MIPS64) || (_MIPS_SIM == _MIPS_SIM_ABI64)
-
-typedef int64_t Atomic64;
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value)
-{
- Atomic64 prev, tmp;
- __asm__ volatile(
- ".set push \n"
- ".set noreorder \n"
-
- "1: \n"
- "lld %0, %5 \n" // prev = *ptr
- "bne %0, %3, 2f \n" // if (prev != old_value) goto 2
- " move %2, %4 \n" // tmp = new_value
- "scd %2, %1 \n" // *ptr = tmp (with atomic check)
- "beqz %2, 1b \n" // start again on atomic error
- " nop \n" // delay slot nop
- "2: \n"
-
- ".set pop \n"
- : "=&r" (prev), "=m" (*ptr),
- "=&r" (tmp)
- : "Ir" (old_value), "r" (new_value),
- "m" (*ptr)
- : "memory"
- );
- return prev;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value)
-{
- Atomic64 temp, old;
- __asm__ volatile(
- ".set push \n"
- ".set noreorder \n"
-
- "1: \n"
- "lld %1, %2 \n" // old = *ptr
- "move %0, %3 \n" // temp = new_value
- "scd %0, %2 \n" // *ptr = temp (with atomic check)
- "beqz %0, 1b \n" // start again on atomic error
- " nop \n" // delay slot nop
-
- ".set pop \n"
- : "=&r" (temp), "=&r" (old),
- "=m" (*ptr)
- : "r" (new_value), "m" (*ptr)
- : "memory"
- );
- return old;
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value)
-{
- Atomic64 old_value = NoBarrier_AtomicExchange(ptr, new_value);
- MemoryBarrier();
- return old_value;
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value)
-{
- Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
- MemoryBarrier();
- return res;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value)
-{
- MemoryBarrier();
- Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
- return res;
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value)
-{
- *ptr = value;
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value)
-{
- MemoryBarrier();
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value)
-{
- *ptr = value;
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value)
-{
- MemoryBarrier();
- *ptr = value;
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr)
-{
- return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr)
-{
- Atomic64 value = *ptr;
- MemoryBarrier();
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr)
-{
- MemoryBarrier();
- return *ptr;
-}
-
-#endif
-
-} // namespace base::subtle
-} // namespace base
-
-#endif // BASE_ATOMICOPS_INTERNALS_MIPS_H_
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops-internals-windows.h b/src/third_party/gperftools-2.5/src/base/atomicops-internals-windows.h
deleted file mode 100644
index 93ced8770d4..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops-internals-windows.h
+++ /dev/null
@@ -1,457 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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
- */
-
-// Implementation of atomic operations using Windows API
-// functions. This file should not be included directly. Clients
-// should instead include "base/atomicops.h".
-
-#ifndef BASE_ATOMICOPS_INTERNALS_WINDOWS_H_
-#define BASE_ATOMICOPS_INTERNALS_WINDOWS_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "base/basictypes.h" // For COMPILE_ASSERT
-
-typedef int32 Atomic32;
-
-#if defined(_WIN64)
-#define BASE_HAS_ATOMIC64 1 // Use only in tests and base/atomic*
-#endif
-
-namespace base {
-namespace subtle {
-
-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
-#if defined(__MINGW32__)
-inline LONG FastInterlockedCompareExchange(volatile LONG* ptr,
- LONG newval, LONG oldval) {
- return ::InterlockedCompareExchange(const_cast<LONG*>(ptr), newval, oldval);
-}
-inline LONG FastInterlockedExchange(volatile LONG* ptr, LONG newval) {
- return ::InterlockedExchange(const_cast<LONG*>(ptr), newval);
-}
-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 = FastInterlockedCompareExchange(
- reinterpret_cast<volatile LONG*>(ptr),
- static_cast<LONG>(new_value),
- static_cast<LONG>(old_value));
- return static_cast<Atomic32>(result);
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- LONG result = FastInterlockedExchange(
- reinterpret_cast<volatile LONG*>(ptr),
- static_cast<LONG>(new_value));
- return static_cast<Atomic32>(result);
-}
-
-inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- // FastInterlockedExchange has both acquire and release memory barriers.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- // FastInterlockedExchange has both acquire and release memory barriers.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-} // namespace base::subtle
-} // namespace base
-
-
-// In msvc8/vs2005, winnt.h already contains a definition for
-// MemoryBarrier in the global namespace. Add it there for earlier
-// versions and forward to it from within the namespace.
-#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
-inline void MemoryBarrier() {
- Atomic32 value = 0;
- base::subtle::NoBarrier_AtomicExchange(&value, 0);
- // actually acts as a barrier in thisd implementation
-}
-#endif
-
-namespace base {
-namespace subtle {
-
-inline void MemoryBarrier() {
- ::MemoryBarrier();
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- Acquire_AtomicExchange(ptr, value);
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value; // works w/o barrier for current Intel chips as of June 2005
- // See comments in Atomic64 version of Release_Store() below.
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
- return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
- Atomic32 value = *ptr;
- return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-// 64-bit operations
-
-#if defined(_WIN64) || defined(__MINGW64__)
-
-// 64-bit low-level operations on 64-bit platform.
-
-COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
-
-// 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 FastInterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) {
- return ::InterlockedExchangePointer(const_cast<PVOID*>(ptr), newval);
-}
-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 = FastInterlockedCompareExchangePointer(
- reinterpret_cast<volatile PVOID*>(ptr),
- reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
- return reinterpret_cast<Atomic64>(result);
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- PVOID result = FastInterlockedExchangePointer(
- reinterpret_cast<volatile PVOID*>(ptr),
- reinterpret_cast<PVOID>(new_value));
- return reinterpret_cast<Atomic64>(result);
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NoBarrier_AtomicExchange(ptr, value);
- // acts as a barrier in this implementation
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
- *ptr = value; // works w/o barrier for current Intel chips as of June 2005
-
- // When new chips come out, check:
- // IA-32 Intel Architecture Software Developer's Manual, Volume 3:
- // System Programming Guide, Chatper 7: Multiple-processor management,
- // Section 7.2, Memory Ordering.
- // Last seen at:
- // http://developer.intel.com/design/pentium4/manuals/index_new.htm
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
- Atomic64 value = *ptr;
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-#else // defined(_WIN64) || defined(__MINGW64__)
-
-// 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-msvc.h, probably.
-
-inline void NotImplementedFatalError(const char *function_name) {
- fprintf(stderr, "64-bit %s() not implemented on this platform\n",
- function_name);
- abort();
-}
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
-#if 0 // Not implemented
- Atomic64 prev;
- __asm__ __volatile__("movl (%3), %%ebx\n\t" // Move 64-bit new_value into
- "movl 4(%3), %%ecx\n\t" // ecx:ebx
- "lock; cmpxchg8b %1\n\t" // If edx:eax (old_value) same
- : "=A" (prev) // as contents of ptr:
- : "m" (*ptr), // ecx:ebx => ptr
- "0" (old_value), // else:
- "r" (&new_value) // old *ptr => edx:eax
- : "memory", "%ebx", "%ecx");
- return prev;
-#else
- NotImplementedFatalError("NoBarrier_CompareAndSwap");
- return 0;
-#endif
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
-#if 0 // Not implemented
- __asm__ __volatile__(
- "movl (%2), %%ebx\n\t" // Move 64-bit new_value into
- "movl 4(%2), %%ecx\n\t" // ecx:ebx
- "0:\n\t"
- "movl %1, %%eax\n\t" // Read contents of ptr into
- "movl 4%1, %%edx\n\t" // edx:eax
- "lock; cmpxchg8b %1\n\t" // Attempt cmpxchg; if *ptr
- "jnz 0b\n\t" // is no longer edx:eax, loop
- : "=A" (new_value)
- : "m" (*ptr),
- "r" (&new_value)
- : "memory", "%ebx", "%ecx");
- return new_value; // Now it's the previous value.
-#else
- NotImplementedFatalError("NoBarrier_AtomicExchange");
- return 0;
-#endif
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptrValue, Atomic64 value)
-{
- __asm {
- movq mm0, value; // Use mmx reg for 64-bit atomic moves
- mov eax, ptrValue;
- movq [eax], mm0;
- emms; // Empty mmx state to enable FP registers
- }
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NoBarrier_AtomicExchange(ptr, value);
- // acts as a barrier in this implementation
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
- NoBarrier_Store(ptr, value);
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptrValue)
-{
- Atomic64 value;
- __asm {
- mov eax, ptrValue;
- movq mm0, [eax]; // Use mmx reg for 64-bit atomic moves
- movq value, mm0;
- emms; // Empty mmx state to enable FP registers
- }
- return value;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
- Atomic64 value = NoBarrier_Load(ptr);
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return NoBarrier_Load(ptr);
-}
-
-#endif // defined(_WIN64) || defined(__MINGW64__)
-
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- // FastInterlockedExchange has both acquire and release memory barriers.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- // FastInterlockedExchange has both acquire and release memory barriers.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-} // namespace base::subtle
-} // namespace base
-
-#endif // BASE_ATOMICOPS_INTERNALS_WINDOWS_H_
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops-internals-x86.cc b/src/third_party/gperftools-2.5/src/base/atomicops-internals-x86.cc
deleted file mode 100644
index c3391e78234..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops-internals-x86.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2007, 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.
- *
- * ---
- * This module gets enough CPU information to optimize the
- * atomicops module on x86.
- */
-
-#include "base/atomicops.h"
-#include "base/basictypes.h"
-#include "base/googleinit.h"
-#include "base/logging.h"
-#include <string.h>
-
-// This file only makes sense with atomicops-internals-x86.h -- it
-// depends on structs that are defined in that file. If atomicops.h
-// doesn't sub-include that file, then we aren't needed, and shouldn't
-// try to do anything.
-#ifdef BASE_ATOMICOPS_INTERNALS_X86_H_
-
-// Inline cpuid instruction. In PIC compilations, %ebx contains the address
-// of the global offset table. To avoid breaking such executables, this code
-// must preserve that register's value across cpuid instructions.
-#if defined(__i386__)
-#define cpuid(a, b, c, d, inp) \
- asm ("mov %%ebx, %%edi\n" \
- "cpuid\n" \
- "xchg %%edi, %%ebx\n" \
- : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
-#elif defined (__x86_64__)
-#define cpuid(a, b, c, d, inp) \
- asm ("mov %%rbx, %%rdi\n" \
- "cpuid\n" \
- "xchg %%rdi, %%rbx\n" \
- : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
-#endif
-
-#if defined(cpuid) // initialize the struct only on x86
-
-// Set the flags so that code will run correctly and conservatively
-// until InitGoogle() is called.
-struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = {
- false, // no SSE2
- false // no cmpxchg16b
-};
-
-// Initialize the AtomicOps_Internalx86CPUFeatures struct.
-static void AtomicOps_Internalx86CPUFeaturesInit() {
- uint32 eax;
- uint32 ebx;
- uint32 ecx;
- uint32 edx;
-
- // Get vendor string (issue CPUID with eax = 0)
- cpuid(eax, ebx, ecx, edx, 0);
- char vendor[13];
- memcpy(vendor, &ebx, 4);
- memcpy(vendor + 4, &edx, 4);
- memcpy(vendor + 8, &ecx, 4);
- vendor[12] = 0;
-
- // get feature flags in ecx/edx, and family/model in eax
- cpuid(eax, ebx, ecx, edx, 1);
-
- int family = (eax >> 8) & 0xf; // family and model fields
- int model = (eax >> 4) & 0xf;
- if (family == 0xf) { // use extended family and model fields
- family += (eax >> 20) & 0xff;
- model += ((eax >> 16) & 0xf) << 4;
- }
-
- // edx bit 26 is SSE2 which we use to tell use whether we can use mfence
- AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1);
-
- // ecx bit 13 indicates whether the cmpxchg16b instruction is supported
- AtomicOps_Internalx86CPUFeatures.has_cmpxchg16b = ((ecx >> 13) & 1);
-}
-
-REGISTER_MODULE_INITIALIZER(atomicops_x86, {
- AtomicOps_Internalx86CPUFeaturesInit();
-});
-
-#endif
-
-#endif /* ifdef BASE_ATOMICOPS_INTERNALS_X86_H_ */
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops-internals-x86.h b/src/third_party/gperftools-2.5/src/base/atomicops-internals-x86.h
deleted file mode 100644
index e441ac7e673..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops-internals-x86.h
+++ /dev/null
@@ -1,391 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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
- */
-
-// Implementation of atomic operations for x86. This file should not
-// be included directly. Clients should instead include
-// "base/atomicops.h".
-
-#ifndef BASE_ATOMICOPS_INTERNALS_X86_H_
-#define BASE_ATOMICOPS_INTERNALS_X86_H_
-#include "base/basictypes.h"
-
-typedef int32_t Atomic32;
-#define BASE_HAS_ATOMIC64 1 // Use only in tests and base/atomic*
-
-
-// NOTE(vchen): x86 does not need to define AtomicWordCastType, because it
-// already matches Atomic32 or Atomic64, depending on the platform.
-
-
-// This struct is not part of the public API of this module; clients may not
-// use it.
-// Features of this x86. Values may not be correct before main() is run,
-// but are set conservatively.
-struct AtomicOps_x86CPUFeatureStruct {
- bool has_sse2; // Processor has SSE2.
- bool has_cmpxchg16b; // Processor supports cmpxchg16b instruction.
-};
-
-ATTRIBUTE_VISIBILITY_HIDDEN
-extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures;
-
-
-#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
-
-
-namespace base {
-namespace subtle {
-
-typedef int64_t Atomic64;
-
-// 32-bit low-level operations on any platform.
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 prev;
- __asm__ __volatile__("lock; cmpxchgl %1,%2"
- : "=a" (prev)
- : "q" (new_value), "m" (*ptr), "0" (old_value)
- : "memory");
- return prev;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- __asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg.
- : "=r" (new_value)
- : "m" (*ptr), "0" (new_value)
- : "memory");
- return new_value; // Now it's the previous value.
-}
-
-inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- Atomic32 old_val = NoBarrier_AtomicExchange(ptr, new_value);
- return old_val;
-}
-
-inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr,
- Atomic32 new_value) {
- // xchgl already has release memory barrier semantics.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
- return x;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
-}
-
-#if defined(__x86_64__)
-
-// 64-bit implementations of memory barrier can be simpler, because it
-// "mfence" is guaranteed to exist.
-inline void MemoryBarrier() {
- __asm__ __volatile__("mfence" : : : "memory");
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
-#else
-
-inline void MemoryBarrier() {
- if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
- __asm__ __volatile__("mfence" : : : "memory");
- } else { // mfence is faster but not present on PIII
- Atomic32 x = 0;
- Acquire_AtomicExchange(&x, 0);
- }
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
- *ptr = value;
- __asm__ __volatile__("mfence" : : : "memory");
- } else {
- Acquire_AtomicExchange(ptr, value);
- }
-}
-#endif
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
- ATOMICOPS_COMPILER_BARRIER();
- *ptr = value; // An x86 store acts as a release barrier.
- // See comments in Atomic64 version of Release_Store(), below.
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
- return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
- Atomic32 value = *ptr; // An x86 load acts as a acquire barrier.
- // See comments in Atomic64 version of Release_Store(), below.
- ATOMICOPS_COMPILER_BARRIER();
- return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-#if defined(__x86_64__)
-
-// 64-bit low-level operations on 64-bit platform.
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev;
- __asm__ __volatile__("lock; cmpxchgq %1,%2"
- : "=a" (prev)
- : "q" (new_value), "m" (*ptr), "0" (old_value)
- : "memory");
- return prev;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- __asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg.
- : "=r" (new_value)
- : "m" (*ptr), "0" (new_value)
- : "memory");
- return new_value; // Now it's the previous value.
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- Atomic64 old_val = NoBarrier_AtomicExchange(ptr, new_value);
- return old_val;
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_value) {
- // xchgq already has release memory barrier semantics.
- return NoBarrier_AtomicExchange(ptr, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- *ptr = value;
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
- ATOMICOPS_COMPILER_BARRIER();
-
- *ptr = value; // An x86 store acts as a release barrier
- // for current AMD/Intel chips as of Jan 2008.
- // See also Acquire_Load(), below.
-
- // When new chips come out, check:
- // IA-32 Intel Architecture Software Developer's Manual, Volume 3:
- // System Programming Guide, Chatper 7: Multiple-processor management,
- // Section 7.2, Memory Ordering.
- // Last seen at:
- // http://developer.intel.com/design/pentium4/manuals/index_new.htm
- //
- // x86 stores/loads fail to act as barriers for a few instructions (clflush
- // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
- // not generated by the compiler, and are rare. Users of these instructions
- // need to know about cache behaviour in any case since all of these involve
- // either flushing cache lines or non-temporal cache hints.
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
- Atomic64 value = *ptr; // An x86 load acts as a acquire barrier,
- // for current AMD/Intel chips as of Jan 2008.
- // See also Release_Store(), above.
- ATOMICOPS_COMPILER_BARRIER();
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return *ptr;
-}
-
-#else // defined(__x86_64__)
-
-// 64-bit low-level operations on 32-bit platform.
-
-#if !((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
-// For compilers older than gcc 4.1, we use inline asm.
-//
-// Potential pitfalls:
-//
-// 1. %ebx points to Global offset table (GOT) with -fPIC.
-// We need to preserve this register.
-// 2. When explicit registers are used in inline asm, the
-// compiler may not be aware of it and might try to reuse
-// the same register for another argument which has constraints
-// that allow it ("r" for example).
-
-inline Atomic64 __sync_val_compare_and_swap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 prev;
- __asm__ __volatile__("push %%ebx\n\t"
- "movl (%3), %%ebx\n\t" // Move 64-bit new_value into
- "movl 4(%3), %%ecx\n\t" // ecx:ebx
- "lock; cmpxchg8b (%1)\n\t"// If edx:eax (old_value) same
- "pop %%ebx\n\t"
- : "=A" (prev) // as contents of ptr:
- : "D" (ptr), // ecx:ebx => ptr
- "0" (old_value), // else:
- "S" (&new_value) // old *ptr => edx:eax
- : "memory", "%ecx");
- return prev;
-}
-#endif // Compiler < gcc-4.1
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_val,
- Atomic64 new_val) {
- return __sync_val_compare_and_swap(ptr, old_val, new_val);
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_val) {
- Atomic64 old_val;
-
- do {
- old_val = *ptr;
- } while (__sync_val_compare_and_swap(ptr, old_val, new_val) != old_val);
-
- return old_val;
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_val) {
- Atomic64 old_val = NoBarrier_AtomicExchange(ptr, new_val);
- return old_val;
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
- Atomic64 new_val) {
- return NoBarrier_AtomicExchange(ptr, new_val);
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
- __asm__ __volatile__("movq %1, %%mm0\n\t" // Use mmx reg for 64-bit atomic
- "movq %%mm0, %0\n\t" // moves (ptr could be read-only)
- "emms\n\t" // Empty mmx state/Reset FP regs
- : "=m" (*ptr)
- : "m" (value)
- : // mark the FP stack and mmx registers as clobbered
- "st", "st(1)", "st(2)", "st(3)", "st(4)",
- "st(5)", "st(6)", "st(7)", "mm0", "mm1",
- "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
- NoBarrier_Store(ptr, value);
- MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
- ATOMICOPS_COMPILER_BARRIER();
- NoBarrier_Store(ptr, value);
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
- Atomic64 value;
- __asm__ __volatile__("movq %1, %%mm0\n\t" // Use mmx reg for 64-bit atomic
- "movq %%mm0, %0\n\t" // moves (ptr could be read-only)
- "emms\n\t" // Empty mmx state/Reset FP regs
- : "=m" (value)
- : "m" (*ptr)
- : // mark the FP stack and mmx registers as clobbered
- "st", "st(1)", "st(2)", "st(3)", "st(4)",
- "st(5)", "st(6)", "st(7)", "mm0", "mm1",
- "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
- return value;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
- Atomic64 value = NoBarrier_Load(ptr);
- ATOMICOPS_COMPILER_BARRIER();
- return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
- MemoryBarrier();
- return NoBarrier_Load(ptr);
-}
-
-#endif // defined(__x86_64__)
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
- return x;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value) {
- return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-} // namespace base::subtle
-} // namespace base
-
-#undef ATOMICOPS_COMPILER_BARRIER
-
-#endif // BASE_ATOMICOPS_INTERNALS_X86_H_
diff --git a/src/third_party/gperftools-2.5/src/base/atomicops.h b/src/third_party/gperftools-2.5/src/base/atomicops.h
deleted file mode 100644
index e2ea8b18e96..00000000000
--- a/src/third_party/gperftools-2.5/src/base/atomicops.h
+++ /dev/null
@@ -1,392 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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
- */
-
-// For atomic operations on statistics counters, see atomic_stats_counter.h.
-// For atomic operations on sequence numbers, see atomic_sequence_num.h.
-// For atomic operations on reference counts, see atomic_refcount.h.
-
-// Some fast atomic operations -- typically with machine-dependent
-// implementations. This file may need editing as Google code is
-// ported to different architectures.
-
-// The routines exported by this module are subtle. If you use them, even if
-// you get the code right, it will depend on careful reasoning about atomicity
-// and memory ordering; it will be less readable, and harder to maintain. If
-// you plan to use these routines, you should have a good reason, such as solid
-// evidence that performance would otherwise suffer, or there being no
-// alternative. You should assume only properties explicitly guaranteed by the
-// specifications in this file. You are almost certainly _not_ writing code
-// just for the x86; if you assume x86 semantics, x86 hardware bugs and
-// implementations on other archtectures will cause your code to break. If you
-// do not know what you are doing, avoid these routines, and use a Mutex.
-//
-// These following lower-level operations are typically useful only to people
-// implementing higher-level synchronization operations like spinlocks,
-// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or
-// a store with appropriate memory-ordering instructions. "Acquire" operations
-// ensure that no later memory access can be reordered ahead of the operation.
-// "Release" operations ensure that no previous memory access can be reordered
-// after the operation. "Barrier" operations have both "Acquire" and "Release"
-// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
-// access.
-//
-// It is incorrect to make direct assignments to/from an atomic variable.
-// You should use one of the Load or Store routines. The NoBarrier
-// versions are provided when no barriers are needed:
-// NoBarrier_Store()
-// NoBarrier_Load()
-// Although there are currently no compiler enforcement, you are encouraged
-// to use these. Moreover, if you choose to use base::subtle::Atomic64 type,
-// you MUST use one of the Load or Store routines to get correct behavior
-// on 32-bit platforms.
-//
-// The intent is eventually to put all of these routines in namespace
-// base::subtle
-
-#ifndef THREAD_ATOMICOPS_H_
-#define THREAD_ATOMICOPS_H_
-
-#include <config.h>
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
-// ------------------------------------------------------------------------
-// Include the platform specific implementations of the types
-// and operations listed below. Implementations are to provide Atomic32
-// and Atomic64 operations. If there is a mismatch between intptr_t and
-// the Atomic32 or Atomic64 types for a platform, the platform-specific header
-// should define the macro, AtomicWordCastType in a clause similar to the
-// following:
-// #if ...pointers are 64 bits...
-// # define AtomicWordCastType base::subtle::Atomic64
-// #else
-// # define AtomicWordCastType Atomic32
-// #endif
-// TODO(csilvers): figure out ARCH_PIII/ARCH_K8 (perhaps via ./configure?)
-// ------------------------------------------------------------------------
-
-#include "base/arm_instruction_set_select.h"
-#define GCC_VERSION (__GNUC__ * 10000 \
- + __GNUC_MINOR__ * 100 \
- + __GNUC_PATCHLEVEL__)
-
-// MongoDB modification: We always have a new enough toolchain to use the GCC atomics
-#if defined(__GNUC__)
-#include "base/atomicops-internals-gcc.h"
-#elif defined(__MACH__) && defined(__APPLE__)
-#include "base/atomicops-internals-macosx.h"
-#elif defined(__GNUC__) && defined(ARMV6)
-#include "base/atomicops-internals-arm-v6plus.h"
-#elif defined(ARMV3)
-#include "base/atomicops-internals-arm-generic.h"
-#elif defined(__GNUC__) && (defined(__i386) || defined(__x86_64__))
-#include "base/atomicops-internals-x86.h"
-#elif defined(_WIN32)
-#include "base/atomicops-internals-windows.h"
-#elif defined(__linux__) && defined(__PPC__)
-#include "base/atomicops-internals-linuxppc.h"
-#elif defined(__GNUC__) && defined(__mips__)
-#include "base/atomicops-internals-mips.h"
-#elif defined(__GNUC__) && GCC_VERSION >= 40700
-#include "base/atomicops-internals-gcc.h"
-#else
-#error You need to implement atomic operations for this architecture
-#endif
-
-// Signed type that can hold a pointer and supports the atomic ops below, as
-// well as atomic loads and stores. Instances must be naturally-aligned.
-typedef intptr_t AtomicWord;
-
-#ifdef AtomicWordCastType
-// ------------------------------------------------------------------------
-// This section is needed only when explicit type casting is required to
-// cast AtomicWord to one of the basic atomic types (Atomic64 or Atomic32).
-// It also serves to document the AtomicWord interface.
-// ------------------------------------------------------------------------
-
-namespace base {
-namespace subtle {
-
-// Atomically execute:
-// result = *ptr;
-// if (*ptr == old_value)
-// *ptr = new_value;
-// return result;
-//
-// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
-// Always return the old value of "*ptr"
-//
-// This routine implies no memory barriers.
-inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
- AtomicWord old_value,
- AtomicWord new_value) {
- return NoBarrier_CompareAndSwap(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr),
- old_value, new_value);
-}
-
-// Atomically store new_value into *ptr, returning the previous value held in
-// *ptr. This routine implies no memory barriers.
-inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
- AtomicWord new_value) {
- return NoBarrier_AtomicExchange(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value);
-}
-
-inline AtomicWord Acquire_AtomicExchange(volatile AtomicWord* ptr,
- AtomicWord new_value) {
- return Acquire_AtomicExchange(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value);
-}
-
-inline AtomicWord Release_AtomicExchange(volatile AtomicWord* ptr,
- AtomicWord new_value) {
- return Release_AtomicExchange(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value);
-}
-
-inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
- AtomicWord old_value,
- AtomicWord new_value) {
- return base::subtle::Acquire_CompareAndSwap(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr),
- old_value, new_value);
-}
-
-inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
- AtomicWord old_value,
- AtomicWord new_value) {
- return base::subtle::Release_CompareAndSwap(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr),
- old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
- NoBarrier_Store(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
-}
-
-inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
- return base::subtle::Acquire_Store(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
-}
-
-inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
- return base::subtle::Release_Store(
- reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
-}
-
-inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
- return NoBarrier_Load(
- reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
-}
-
-inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
- return base::subtle::Acquire_Load(
- reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
-}
-
-inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
- return base::subtle::Release_Load(
- reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
-}
-
-} // namespace base::subtle
-} // namespace base
-#endif // AtomicWordCastType
-
-// ------------------------------------------------------------------------
-// Commented out type definitions and method declarations for documentation
-// of the interface provided by this module.
-// ------------------------------------------------------------------------
-
-#if 0
-
-// Signed 32-bit type that supports the atomic ops below, as well as atomic
-// loads and stores. Instances must be naturally aligned. This type differs
-// from AtomicWord in 64-bit binaries where AtomicWord is 64-bits.
-typedef int32_t Atomic32;
-
-// Corresponding operations on Atomic32
-namespace base {
-namespace subtle {
-
-// Signed 64-bit type that supports the atomic ops below, as well as atomic
-// loads and stores. Instances must be naturally aligned. This type differs
-// from AtomicWord in 32-bit binaries where AtomicWord is 32-bits.
-typedef int64_t Atomic64;
-
-Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value);
-Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
-Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
-Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
-Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value);
-Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value);
-void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
-void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
-void Release_Store(volatile Atomic32* ptr, Atomic32 value);
-Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
-Atomic32 Acquire_Load(volatile const Atomic32* ptr);
-Atomic32 Release_Load(volatile const Atomic32* ptr);
-
-// Corresponding operations on Atomic64
-Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value);
-Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
-Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
-Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
-
-Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value);
-Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
- Atomic64 old_value,
- Atomic64 new_value);
-void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
-void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
-void Release_Store(volatile Atomic64* ptr, Atomic64 value);
-Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
-Atomic64 Acquire_Load(volatile const Atomic64* ptr);
-Atomic64 Release_Load(volatile const Atomic64* ptr);
-} // namespace base::subtle
-} // namespace base
-
-void MemoryBarrier();
-
-#endif // 0
-
-
-// ------------------------------------------------------------------------
-// The following are to be deprecated when all uses have been changed to
-// use the base::subtle namespace.
-// ------------------------------------------------------------------------
-
-#ifdef AtomicWordCastType
-// AtomicWord versions to be deprecated
-inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
- AtomicWord old_value,
- AtomicWord new_value) {
- return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
- AtomicWord old_value,
- AtomicWord new_value) {
- return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
- return base::subtle::Acquire_Store(ptr, value);
-}
-
-inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
- return base::subtle::Release_Store(ptr, value);
-}
-
-inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
- return base::subtle::Acquire_Load(ptr);
-}
-
-inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
- return base::subtle::Release_Load(ptr);
-}
-#endif // AtomicWordCastType
-
-// 32-bit Acquire/Release operations to be deprecated.
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value);
-}
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
- Atomic32 old_value,
- Atomic32 new_value) {
- return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
-}
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
- base::subtle::Acquire_Store(ptr, value);
-}
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
- return base::subtle::Release_Store(ptr, value);
-}
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
- return base::subtle::Acquire_Load(ptr);
-}
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
- return base::subtle::Release_Load(ptr);
-}
-
-#ifdef BASE_HAS_ATOMIC64
-
-// 64-bit Acquire/Release operations to be deprecated.
-
-inline base::subtle::Atomic64 Acquire_CompareAndSwap(
- volatile base::subtle::Atomic64* ptr,
- base::subtle::Atomic64 old_value, base::subtle::Atomic64 new_value) {
- return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value);
-}
-inline base::subtle::Atomic64 Release_CompareAndSwap(
- volatile base::subtle::Atomic64* ptr,
- base::subtle::Atomic64 old_value, base::subtle::Atomic64 new_value) {
- return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
-}
-inline void Acquire_Store(
- volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
- base::subtle::Acquire_Store(ptr, value);
-}
-inline void Release_Store(
- volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
- return base::subtle::Release_Store(ptr, value);
-}
-inline base::subtle::Atomic64 Acquire_Load(
- volatile const base::subtle::Atomic64* ptr) {
- return base::subtle::Acquire_Load(ptr);
-}
-inline base::subtle::Atomic64 Release_Load(
- volatile const base::subtle::Atomic64* ptr) {
- return base::subtle::Release_Load(ptr);
-}
-
-#endif // BASE_HAS_ATOMIC64
-
-#endif // THREAD_ATOMICOPS_H_
diff --git a/src/third_party/gperftools-2.5/src/base/basictypes.h b/src/third_party/gperftools-2.5/src/base/basictypes.h
deleted file mode 100644
index f0e25daf8f1..00000000000
--- a/src/third_party/gperftools-2.5/src/base/basictypes.h
+++ /dev/null
@@ -1,392 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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.
-
-#ifndef _BASICTYPES_H_
-#define _BASICTYPES_H_
-
-#include <config.h>
-#include <string.h> // for memcpy()
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h> // gets us PRId64, etc
-#endif
-
-// To use this in an autoconf setting, make sure you run the following
-// autoconf macros:
-// AC_HEADER_STDC /* for stdint_h and inttypes_h */
-// AC_CHECK_TYPES([__int64]) /* defined in some windows platforms */
-
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h> // uint16_t might be here; PRId64 too.
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h> // to get uint16_t (ISO naming madness)
-#endif
-#include <sys/types.h> // our last best hope for uint16_t
-
-// Standard typedefs
-// All Google code is compiled with -funsigned-char to make "char"
-// unsigned. Google code therefore doesn't need a "uchar" type.
-// TODO(csilvers): how do we make sure unsigned-char works on non-gcc systems?
-typedef signed char schar;
-typedef int8_t int8;
-typedef int16_t int16;
-typedef int32_t int32;
-typedef int64_t int64;
-
-// NOTE: unsigned types are DANGEROUS in loops and other arithmetical
-// places. Use the signed types unless your variable represents a bit
-// pattern (eg a hash value) or you really need the extra bit. Do NOT
-// use 'unsigned' to express "this value should always be positive";
-// use assertions for this.
-
-typedef uint8_t uint8;
-typedef uint16_t uint16;
-typedef uint32_t uint32;
-typedef uint64_t uint64;
-
-const uint16 kuint16max = ( (uint16) 0xFFFF);
-const uint32 kuint32max = ( (uint32) 0xFFFFFFFF);
-const uint64 kuint64max = ( (((uint64) kuint32max) << 32) | kuint32max );
-
-const int8 kint8max = ( ( int8) 0x7F);
-const int16 kint16max = ( ( int16) 0x7FFF);
-const int32 kint32max = ( ( int32) 0x7FFFFFFF);
-const int64 kint64max = ( ((( int64) kint32max) << 32) | kuint32max );
-
-const int8 kint8min = ( ( int8) 0x80);
-const int16 kint16min = ( ( int16) 0x8000);
-const int32 kint32min = ( ( int32) 0x80000000);
-const int64 kint64min = ( (((uint64) kint32min) << 32) | 0 );
-
-// Define the "portable" printf and scanf macros, if they're not
-// already there (via the inttypes.h we #included above, hopefully).
-// Mostly it's old systems that don't support inttypes.h, so we assume
-// they're 32 bit.
-#ifndef PRIx64
-#define PRIx64 "llx"
-#endif
-#ifndef SCNx64
-#define SCNx64 "llx"
-#endif
-#ifndef PRId64
-#define PRId64 "lld"
-#endif
-#ifndef SCNd64
-#define SCNd64 "lld"
-#endif
-#ifndef PRIu64
-#define PRIu64 "llu"
-#endif
-#ifndef PRIxPTR
-#define PRIxPTR "lx"
-#endif
-
-// Also allow for printing of a pthread_t.
-#define GPRIuPTHREAD "lu"
-#define GPRIxPTHREAD "lx"
-#if defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__APPLE__) || defined(__FreeBSD__)
-#define PRINTABLE_PTHREAD(pthreadt) reinterpret_cast<uintptr_t>(pthreadt)
-#else
-#define PRINTABLE_PTHREAD(pthreadt) pthreadt
-#endif
-
-// A macro to disallow the evil copy constructor and operator= functions
-// This should be used in the private: declarations for a class
-#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
-// An alternate name that leaves out the moral judgment... :-)
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) DISALLOW_EVIL_CONSTRUCTORS(TypeName)
-
-// The COMPILE_ASSERT macro can be used to verify that a compile time
-// expression is true. For example, you could use it to verify the
-// size of a static array:
-//
-// COMPILE_ASSERT(sizeof(num_content_type_names) == sizeof(int),
-// content_type_names_incorrect_size);
-//
-// or to make sure a struct is smaller than a certain size:
-//
-// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
-//
-// The second argument to the macro is the name of the variable. If
-// the expression is false, most compilers will issue a warning/error
-// containing the name of the variable.
-//
-// Implementation details of COMPILE_ASSERT:
-//
-// - COMPILE_ASSERT works by defining an array type that has -1
-// elements (and thus is invalid) when the expression is false.
-//
-// - The simpler definition
-//
-// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
-//
-// does not work, as gcc supports variable-length arrays whose sizes
-// are determined at run-time (this is gcc's extension and not part
-// of the C++ standard). As a result, gcc fails to reject the
-// following code with the simple definition:
-//
-// int foo;
-// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
-// // not a compile-time constant.
-//
-// - By using the type CompileAssert<(bool(expr))>, we ensures that
-// expr is a compile-time constant. (Template arguments must be
-// determined at compile-time.)
-//
-// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
-// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
-//
-// CompileAssert<bool(expr)>
-//
-// instead, these compilers will refuse to compile
-//
-// COMPILE_ASSERT(5 > 0, some_message);
-//
-// (They seem to think the ">" in "5 > 0" marks the end of the
-// template argument list.)
-//
-// - The array size is (bool(expr) ? 1 : -1), instead of simply
-//
-// ((expr) ? 1 : -1).
-//
-// This is to avoid running into a bug in MS VC 7.1, which
-// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
-
-template <bool>
-struct CompileAssert {
-};
-
-#ifdef HAVE___ATTRIBUTE__
-# define ATTRIBUTE_UNUSED __attribute__((unused))
-#else
-# define ATTRIBUTE_UNUSED
-#endif
-
-#define COMPILE_ASSERT(expr, msg) \
- typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ATTRIBUTE_UNUSED
-
-#define arraysize(a) (sizeof(a) / sizeof(*(a)))
-
-#define OFFSETOF_MEMBER(strct, field) \
- (reinterpret_cast<char*>(&reinterpret_cast<strct*>(16)->field) - \
- reinterpret_cast<char*>(16))
-
-// bit_cast<Dest,Source> implements the equivalent of
-// "*reinterpret_cast<Dest*>(&source)".
-//
-// The reinterpret_cast method would produce undefined behavior
-// according to ISO C++ specification section 3.10 -15 -.
-// bit_cast<> calls memcpy() which is blessed by the standard,
-// especially by the example in section 3.9.
-//
-// Fortunately memcpy() is very fast. In optimized mode, with a
-// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
-// code with the minimal amount of data movement. On a 32-bit system,
-// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
-// compiles to two loads and two stores.
-
-template <class Dest, class Source>
-inline Dest bit_cast(const Source& source) {
- COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), bitcasting_unequal_sizes);
- Dest dest;
- memcpy(&dest, &source, sizeof(dest));
- return dest;
-}
-
-#ifdef HAVE___ATTRIBUTE__
-# define ATTRIBUTE_WEAK __attribute__((weak))
-# define ATTRIBUTE_NOINLINE __attribute__((noinline))
-#else
-# define ATTRIBUTE_WEAK
-# define ATTRIBUTE_NOINLINE
-#endif
-
-#if defined(HAVE___ATTRIBUTE__) && defined(__ELF__)
-# define ATTRIBUTE_VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
-#else
-# define ATTRIBUTE_VISIBILITY_HIDDEN
-#endif
-
-// Section attributes are supported for both ELF and Mach-O, but in
-// very different ways. Here's the API we provide:
-// 1) ATTRIBUTE_SECTION: put this with the declaration of all functions
-// you want to be in the same linker section
-// 2) DEFINE_ATTRIBUTE_SECTION_VARS: must be called once per unique
-// name. You want to make sure this is executed before any
-// DECLARE_ATTRIBUTE_SECTION_VARS; the easiest way is to put them
-// in the same .cc file. Put this call at the global level.
-// 3) INIT_ATTRIBUTE_SECTION_VARS: you can scatter calls to this in
-// multiple places to help ensure execution before any
-// DECLARE_ATTRIBUTE_SECTION_VARS. You must have at least one
-// DEFINE, but you can have many INITs. Put each in its own scope.
-// 4) DECLARE_ATTRIBUTE_SECTION_VARS: must be called before using
-// ATTRIBUTE_SECTION_START or ATTRIBUTE_SECTION_STOP on a name.
-// Put this call at the global level.
-// 5) ATTRIBUTE_SECTION_START/ATTRIBUTE_SECTION_STOP: call this to say
-// where in memory a given section is. All functions declared with
-// ATTRIBUTE_SECTION are guaranteed to be between START and STOP.
-
-#if defined(HAVE___ATTRIBUTE__) && defined(__ELF__)
-# define ATTRIBUTE_SECTION(name) __attribute__ ((section (#name)))
-
- // Weak section declaration to be used as a global declaration
- // for ATTRIBUTE_SECTION_START|STOP(name) to compile and link
- // even without functions with ATTRIBUTE_SECTION(name).
-# define DECLARE_ATTRIBUTE_SECTION_VARS(name) \
- extern char __start_##name[] ATTRIBUTE_WEAK; \
- extern char __stop_##name[] ATTRIBUTE_WEAK
-# define INIT_ATTRIBUTE_SECTION_VARS(name) // no-op for ELF
-# define DEFINE_ATTRIBUTE_SECTION_VARS(name) // no-op for ELF
-
- // Return void* pointers to start/end of a section of code with functions
- // having ATTRIBUTE_SECTION(name), or 0 if no such function exists.
- // One must DECLARE_ATTRIBUTE_SECTION(name) for this to compile and link.
-# define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(__start_##name))
-# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name))
-# define HAVE_ATTRIBUTE_SECTION_START 1
-
-#elif defined(HAVE___ATTRIBUTE__) && defined(__MACH__)
-# define ATTRIBUTE_SECTION(name) __attribute__ ((section ("__TEXT, " #name)))
-
-#include <mach-o/getsect.h>
-#include <mach-o/dyld.h>
-class AssignAttributeStartEnd {
- public:
- AssignAttributeStartEnd(const char* name, char** pstart, char** pend) {
- // Find out what dynamic library name is defined in
- if (_dyld_present()) {
- for (int i = _dyld_image_count() - 1; i >= 0; --i) {
- const mach_header* hdr = _dyld_get_image_header(i);
-#ifdef MH_MAGIC_64
- if (hdr->magic == MH_MAGIC_64) {
- uint64_t len;
- *pstart = getsectdatafromheader_64((mach_header_64*)hdr,
- "__TEXT", name, &len);
- if (*pstart) { // NULL if not defined in this dynamic library
- *pstart += _dyld_get_image_vmaddr_slide(i); // correct for reloc
- *pend = *pstart + len;
- return;
- }
- }
-#endif
- if (hdr->magic == MH_MAGIC) {
- uint32_t len;
- *pstart = getsectdatafromheader(hdr, "__TEXT", name, &len);
- if (*pstart) { // NULL if not defined in this dynamic library
- *pstart += _dyld_get_image_vmaddr_slide(i); // correct for reloc
- *pend = *pstart + len;
- return;
- }
- }
- }
- }
- // If we get here, not defined in a dll at all. See if defined statically.
- unsigned long len; // don't ask me why this type isn't uint32_t too...
- *pstart = getsectdata("__TEXT", name, &len);
- *pend = *pstart + len;
- }
-};
-
-#define DECLARE_ATTRIBUTE_SECTION_VARS(name) \
- extern char* __start_##name; \
- extern char* __stop_##name
-
-#define INIT_ATTRIBUTE_SECTION_VARS(name) \
- DECLARE_ATTRIBUTE_SECTION_VARS(name); \
- static const AssignAttributeStartEnd __assign_##name( \
- #name, &__start_##name, &__stop_##name)
-
-#define DEFINE_ATTRIBUTE_SECTION_VARS(name) \
- char* __start_##name, *__stop_##name; \
- INIT_ATTRIBUTE_SECTION_VARS(name)
-
-# define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(__start_##name))
-# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name))
-# define HAVE_ATTRIBUTE_SECTION_START 1
-
-#else // not HAVE___ATTRIBUTE__ && __ELF__, nor HAVE___ATTRIBUTE__ && __MACH__
-# define ATTRIBUTE_SECTION(name)
-# define DECLARE_ATTRIBUTE_SECTION_VARS(name)
-# define INIT_ATTRIBUTE_SECTION_VARS(name)
-# define DEFINE_ATTRIBUTE_SECTION_VARS(name)
-# define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(0))
-# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(0))
-
-#endif // HAVE___ATTRIBUTE__ and __ELF__ or __MACH__
-
-#if defined(HAVE___ATTRIBUTE__)
-# if (defined(__i386__) || defined(__x86_64__))
-# define CACHELINE_ALIGNED __attribute__((aligned(64)))
-# elif (defined(__PPC__) || defined(__PPC64__))
-# define CACHELINE_ALIGNED __attribute__((aligned(16)))
-# elif (defined(__arm__))
-# define CACHELINE_ALIGNED __attribute__((aligned(64)))
- // some ARMs have shorter cache lines (ARM1176JZF-S is 32 bytes for example) but obviously 64-byte aligned implies 32-byte aligned
-# elif (defined(__mips__))
-# define CACHELINE_ALIGNED __attribute__((aligned(128)))
-# elif (defined(__aarch64__))
-# define CACHELINE_ALIGNED __attribute__((aligned(64)))
- // implementation specific, Cortex-A53 and 57 should have 64 bytes
-# elif (defined(__s390x__))
-# define CACHELINE_ALIGNED __attribute__((aligned(256)))
-# else
-# error Could not determine cache line length - unknown architecture
-# endif
-#else
-# define CACHELINE_ALIGNED
-#endif // defined(HAVE___ATTRIBUTE__) && (__i386__ || __x86_64__)
-
-// Structure for discovering alignment
-union MemoryAligner {
- void* p;
- double d;
- size_t s;
-} CACHELINE_ALIGNED;
-
-// The following enum should be used only as a constructor argument to indicate
-// that the variable has static storage class, and that the constructor should
-// do nothing to its state. It indicates to the reader that it is legal to
-// declare a static nistance of the class, provided the constructor is given
-// the base::LINKER_INITIALIZED argument. Normally, it is unsafe to declare a
-// static variable that has a constructor or a destructor because invocation
-// order is undefined. However, IF the type can be initialized by filling with
-// zeroes (which the loader does for static variables), AND the destructor also
-// does nothing to the storage, then a constructor declared as
-// explicit MyClass(base::LinkerInitialized x) {}
-// and invoked as
-// static MyClass my_variable_name(base::LINKER_INITIALIZED);
-namespace base {
-enum LinkerInitialized { LINKER_INITIALIZED };
-}
-
-#endif // _BASICTYPES_H_
diff --git a/src/third_party/gperftools-2.5/src/base/commandlineflags.h b/src/third_party/gperftools-2.5/src/base/commandlineflags.h
deleted file mode 100644
index f54776aba5b..00000000000
--- a/src/third_party/gperftools-2.5/src/base/commandlineflags.h
+++ /dev/null
@@ -1,166 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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.
-
-// ---
-// This file is a compatibility layer that defines Google's version of
-// command line flags that are used for configuration.
-//
-// We put flags into their own namespace. It is purposefully
-// named in an opaque way that people should have trouble typing
-// directly. The idea is that DEFINE puts the flag in the weird
-// namespace, and DECLARE imports the flag from there into the
-// current namespace. The net result is to force people to use
-// DECLARE to get access to a flag, rather than saying
-// extern bool FLAGS_logtostderr;
-// or some such instead. We want this so we can put extra
-// functionality (like sanity-checking) in DECLARE if we want,
-// and make sure it is picked up everywhere.
-//
-// We also put the type of the variable in the namespace, so that
-// people can't DECLARE_int32 something that they DEFINE_bool'd
-// elsewhere.
-#ifndef BASE_COMMANDLINEFLAGS_H_
-#define BASE_COMMANDLINEFLAGS_H_
-
-#include <config.h>
-#include <string>
-#include <string.h> // for memchr
-#include <stdlib.h> // for getenv
-#include "base/basictypes.h"
-
-#define DECLARE_VARIABLE(type, name) \
- namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead { \
- extern PERFTOOLS_DLL_DECL type FLAGS_##name; \
- } \
- using FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead::FLAGS_##name
-
-#define DEFINE_VARIABLE(type, name, value, meaning) \
- namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead { \
- PERFTOOLS_DLL_DECL type FLAGS_##name(value); \
- char FLAGS_no##name; \
- } \
- using FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead::FLAGS_##name
-
-// bool specialization
-#define DECLARE_bool(name) \
- DECLARE_VARIABLE(bool, name)
-#define DEFINE_bool(name, value, meaning) \
- DEFINE_VARIABLE(bool, name, value, meaning)
-
-// int32 specialization
-#define DECLARE_int32(name) \
- DECLARE_VARIABLE(int32, name)
-#define DEFINE_int32(name, value, meaning) \
- DEFINE_VARIABLE(int32, name, value, meaning)
-
-// int64 specialization
-#define DECLARE_int64(name) \
- DECLARE_VARIABLE(int64, name)
-#define DEFINE_int64(name, value, meaning) \
- DEFINE_VARIABLE(int64, name, value, meaning)
-
-#define DECLARE_uint64(name) \
- DECLARE_VARIABLE(uint64, name)
-#define DEFINE_uint64(name, value, meaning) \
- DEFINE_VARIABLE(uint64, name, value, meaning)
-
-// double specialization
-#define DECLARE_double(name) \
- DECLARE_VARIABLE(double, name)
-#define DEFINE_double(name, value, meaning) \
- DEFINE_VARIABLE(double, name, value, meaning)
-
-// Special case for string, because we have to specify the namespace
-// std::string, which doesn't play nicely with our FLAG__namespace hackery.
-#define DECLARE_string(name) \
- namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead { \
- extern std::string FLAGS_##name; \
- } \
- using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
-#define DEFINE_string(name, value, meaning) \
- namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead { \
- std::string FLAGS_##name(value); \
- char FLAGS_no##name; \
- } \
- using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
-
-// implemented in sysinfo.cc
-namespace tcmalloc {
- namespace commandlineflags {
-
- inline bool StringToBool(const char *value, bool def) {
- if (!value) {
- return def;
- }
- return memchr("tTyY1\0", value[0], 6) != NULL;
- }
-
- inline int StringToInt(const char *value, int def) {
- if (!value) {
- return def;
- }
- return strtol(value, NULL, 10);
- }
-
- inline long long StringToLongLong(const char *value, long long def) {
- if (!value) {
- return def;
- }
- return strtoll(value, NULL, 10);
- }
-
- inline double StringToDouble(const char *value, double def) {
- if (!value) {
- return def;
- }
- return strtod(value, NULL);
- }
- }
-}
-
-// These macros (could be functions, but I don't want to bother with a .cc
-// file), make it easier to initialize flags from the environment.
-
-#define EnvToString(envname, dflt) \
- (!getenv(envname) ? (dflt) : getenv(envname))
-
-#define EnvToBool(envname, dflt) \
- tcmalloc::commandlineflags::StringToBool(getenv(envname), dflt)
-
-#define EnvToInt(envname, dflt) \
- tcmalloc::commandlineflags::StringToInt(getenv(envname), dflt)
-
-#define EnvToInt64(envname, dflt) \
- tcmalloc::commandlineflags::StringToLongLong(getenv(envname), dflt)
-
-#define EnvToDouble(envname, dflt) \
- tcmalloc::commandlineflags::StringToDouble(getenv(envname), dflt)
-
-#endif // BASE_COMMANDLINEFLAGS_H_
diff --git a/src/third_party/gperftools-2.5/src/base/dynamic_annotations.c b/src/third_party/gperftools-2.5/src/base/dynamic_annotations.c
deleted file mode 100644
index 87bd2ecde97..00000000000
--- a/src/third_party/gperftools-2.5/src/base/dynamic_annotations.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (c) 2008-2009, 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: Kostya Serebryany
- */
-
-#ifdef __cplusplus
-# error "This file should be built as pure C to avoid name mangling"
-#endif
-
-#include "config.h"
-#include <stdlib.h>
-#include <string.h>
-
-#include "base/dynamic_annotations.h"
-#include "getenv_safe.h" // for TCMallocGetenvSafe
-
-#ifdef __GNUC__
-/* valgrind.h uses gcc extensions so it won't build with other compilers */
-# ifdef HAVE_VALGRIND_H /* prefer the user's copy if they have it */
-# include <valgrind.h>
-# else /* otherwise just use the copy that we have */
-# include "third_party/valgrind.h"
-# endif
-#endif
-
-/* Compiler-based ThreadSanitizer defines
- DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
- and provides its own definitions of the functions. */
-
-#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
-# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
-#endif
-
-/* Each function is empty and called (via a macro) only in debug mode.
- The arguments are captured by dynamic tools at runtime. */
-
-#if DYNAMIC_ANNOTATIONS_ENABLED == 1 \
- && DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
-
-void AnnotateRWLockCreate(const char *file, int line,
- const volatile void *lock){}
-void AnnotateRWLockDestroy(const char *file, int line,
- const volatile void *lock){}
-void AnnotateRWLockAcquired(const char *file, int line,
- const volatile void *lock, long is_w){}
-void AnnotateRWLockReleased(const char *file, int line,
- const volatile void *lock, long is_w){}
-void AnnotateBarrierInit(const char *file, int line,
- const volatile void *barrier, long count,
- long reinitialization_allowed) {}
-void AnnotateBarrierWaitBefore(const char *file, int line,
- const volatile void *barrier) {}
-void AnnotateBarrierWaitAfter(const char *file, int line,
- const volatile void *barrier) {}
-void AnnotateBarrierDestroy(const char *file, int line,
- const volatile void *barrier) {}
-
-void AnnotateCondVarWait(const char *file, int line,
- const volatile void *cv,
- const volatile void *lock){}
-void AnnotateCondVarSignal(const char *file, int line,
- const volatile void *cv){}
-void AnnotateCondVarSignalAll(const char *file, int line,
- const volatile void *cv){}
-void AnnotatePublishMemoryRange(const char *file, int line,
- const volatile void *address,
- long size){}
-void AnnotateUnpublishMemoryRange(const char *file, int line,
- const volatile void *address,
- long size){}
-void AnnotatePCQCreate(const char *file, int line,
- const volatile void *pcq){}
-void AnnotatePCQDestroy(const char *file, int line,
- const volatile void *pcq){}
-void AnnotatePCQPut(const char *file, int line,
- const volatile void *pcq){}
-void AnnotatePCQGet(const char *file, int line,
- const volatile void *pcq){}
-void AnnotateNewMemory(const char *file, int line,
- const volatile void *mem,
- long size){}
-void AnnotateExpectRace(const char *file, int line,
- const volatile void *mem,
- const char *description){}
-void AnnotateBenignRace(const char *file, int line,
- const volatile void *mem,
- const char *description){}
-void AnnotateBenignRaceSized(const char *file, int line,
- const volatile void *mem,
- long size,
- const char *description) {}
-void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
- const volatile void *mu){}
-void AnnotateTraceMemory(const char *file, int line,
- const volatile void *arg){}
-void AnnotateThreadName(const char *file, int line,
- const char *name){}
-void AnnotateIgnoreReadsBegin(const char *file, int line){}
-void AnnotateIgnoreReadsEnd(const char *file, int line){}
-void AnnotateIgnoreWritesBegin(const char *file, int line){}
-void AnnotateIgnoreWritesEnd(const char *file, int line){}
-void AnnotateEnableRaceDetection(const char *file, int line, int enable){}
-void AnnotateNoOp(const char *file, int line,
- const volatile void *arg){}
-void AnnotateFlushState(const char *file, int line){}
-
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED == 1
- && DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
-
-#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
-
-static int GetRunningOnValgrind(void) {
-#ifdef RUNNING_ON_VALGRIND
- if (RUNNING_ON_VALGRIND) return 1;
-#endif
- const char *running_on_valgrind_str = TCMallocGetenvSafe("RUNNING_ON_VALGRIND");
- if (running_on_valgrind_str) {
- return strcmp(running_on_valgrind_str, "0") != 0;
- }
- return 0;
-}
-
-/* See the comments in dynamic_annotations.h */
-int RunningOnValgrind(void) {
- static volatile int running_on_valgrind = -1;
- int local_running_on_valgrind = running_on_valgrind;
- /* C doesn't have thread-safe initialization of statics, and we
- don't want to depend on pthread_once here, so hack it. */
- ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack");
- if (local_running_on_valgrind == -1)
- running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
- return local_running_on_valgrind;
-}
-
-#endif /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
-
-/* See the comments in dynamic_annotations.h */
-double ValgrindSlowdown(void) {
- /* Same initialization hack as in RunningOnValgrind(). */
- static volatile double slowdown = 0.0;
- double local_slowdown = slowdown;
- ANNOTATE_BENIGN_RACE(&slowdown, "safe hack");
- if (RunningOnValgrind() == 0) {
- return 1.0;
- }
- if (local_slowdown == 0.0) {
- char *env = getenv("VALGRIND_SLOWDOWN");
- slowdown = local_slowdown = env ? atof(env) : 50.0;
- }
- return local_slowdown;
-}
diff --git a/src/third_party/gperftools-2.5/src/base/dynamic_annotations.h b/src/third_party/gperftools-2.5/src/base/dynamic_annotations.h
deleted file mode 100644
index 4669315ced3..00000000000
--- a/src/third_party/gperftools-2.5/src/base/dynamic_annotations.h
+++ /dev/null
@@ -1,627 +0,0 @@
-/* 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: Kostya Serebryany
- */
-
-/* This file defines dynamic annotations for use with dynamic analysis
- tool such as valgrind, PIN, etc.
-
- Dynamic annotation is a source code annotation that affects
- the generated code (that is, the annotation is not a comment).
- Each such annotation is attached to a particular
- instruction and/or to a particular object (address) in the program.
-
- The annotations that should be used by users are macros in all upper-case
- (e.g., ANNOTATE_NEW_MEMORY).
-
- Actual implementation of these macros may differ depending on the
- dynamic analysis tool being used.
-
- See http://code.google.com/p/data-race-test/ for more information.
-
- This file supports the following dynamic analysis tools:
- - None (DYNAMIC_ANNOTATIONS_ENABLED is not defined or zero).
- Macros are defined empty.
- - ThreadSanitizer, Helgrind, DRD (DYNAMIC_ANNOTATIONS_ENABLED is 1).
- Macros are defined as calls to non-inlinable empty functions
- that are intercepted by Valgrind. */
-
-#ifndef BASE_DYNAMIC_ANNOTATIONS_H_
-#define BASE_DYNAMIC_ANNOTATIONS_H_
-
-#ifndef DYNAMIC_ANNOTATIONS_ENABLED
-# define DYNAMIC_ANNOTATIONS_ENABLED 0
-#endif
-
-#if DYNAMIC_ANNOTATIONS_ENABLED != 0
-
- /* -------------------------------------------------------------
- Annotations useful when implementing condition variables such as CondVar,
- using conditional critical sections (Await/LockWhen) and when constructing
- user-defined synchronization mechanisms.
-
- The annotations ANNOTATE_HAPPENS_BEFORE() and ANNOTATE_HAPPENS_AFTER() can
- be used to define happens-before arcs in user-defined synchronization
- mechanisms: the race detector will infer an arc from the former to the
- latter when they share the same argument pointer.
-
- Example 1 (reference counting):
-
- void Unref() {
- ANNOTATE_HAPPENS_BEFORE(&refcount_);
- if (AtomicDecrementByOne(&refcount_) == 0) {
- ANNOTATE_HAPPENS_AFTER(&refcount_);
- delete this;
- }
- }
-
- Example 2 (message queue):
-
- void MyQueue::Put(Type *e) {
- MutexLock lock(&mu_);
- ANNOTATE_HAPPENS_BEFORE(e);
- PutElementIntoMyQueue(e);
- }
-
- Type *MyQueue::Get() {
- MutexLock lock(&mu_);
- Type *e = GetElementFromMyQueue();
- ANNOTATE_HAPPENS_AFTER(e);
- return e;
- }
-
- Note: when possible, please use the existing reference counting and message
- queue implementations instead of inventing new ones. */
-
- /* Report that wait on the condition variable at address "cv" has succeeded
- and the lock at address "lock" is held. */
- #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \
- AnnotateCondVarWait(__FILE__, __LINE__, cv, lock)
-
- /* Report that wait on the condition variable at "cv" has succeeded. Variant
- w/o lock. */
- #define ANNOTATE_CONDVAR_WAIT(cv) \
- AnnotateCondVarWait(__FILE__, __LINE__, cv, NULL)
-
- /* Report that we are about to signal on the condition variable at address
- "cv". */
- #define ANNOTATE_CONDVAR_SIGNAL(cv) \
- AnnotateCondVarSignal(__FILE__, __LINE__, cv)
-
- /* Report that we are about to signal_all on the condition variable at "cv". */
- #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \
- AnnotateCondVarSignalAll(__FILE__, __LINE__, cv)
-
- /* Annotations for user-defined synchronization mechanisms. */
- #define ANNOTATE_HAPPENS_BEFORE(obj) ANNOTATE_CONDVAR_SIGNAL(obj)
- #define ANNOTATE_HAPPENS_AFTER(obj) ANNOTATE_CONDVAR_WAIT(obj)
-
- /* Report that the bytes in the range [pointer, pointer+size) are about
- to be published safely. The race checker will create a happens-before
- arc from the call ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) to
- subsequent accesses to this memory.
- Note: this annotation may not work properly if the race detector uses
- sampling, i.e. does not observe all memory accesses.
- */
- #define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
- AnnotatePublishMemoryRange(__FILE__, __LINE__, pointer, size)
-
- /* DEPRECATED. Don't use it. */
- #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) \
- AnnotateUnpublishMemoryRange(__FILE__, __LINE__, pointer, size)
-
- /* DEPRECATED. Don't use it. */
- #define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size) \
- do { \
- ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size); \
- ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size); \
- } while (0)
-
- /* Instruct the tool to create a happens-before arc between mu->Unlock() and
- mu->Lock(). This annotation may slow down the race detector and hide real
- races. Normally it is used only when it would be difficult to annotate each
- of the mutex's critical sections individually using the annotations above.
- This annotation makes sense only for hybrid race detectors. For pure
- happens-before detectors this is a no-op. For more details see
- http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */
- #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \
- AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
-
- /* Deprecated. Use ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. */
- #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \
- AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
-
- /* -------------------------------------------------------------
- Annotations useful when defining memory allocators, or when memory that
- was protected in one way starts to be protected in another. */
-
- /* Report that a new memory at "address" of size "size" has been allocated.
- This might be used when the memory has been retrieved from a free list and
- is about to be reused, or when a the locking discipline for a variable
- changes. */
- #define ANNOTATE_NEW_MEMORY(address, size) \
- AnnotateNewMemory(__FILE__, __LINE__, address, size)
-
- /* -------------------------------------------------------------
- Annotations useful when defining FIFO queues that transfer data between
- threads. */
-
- /* Report that the producer-consumer queue (such as ProducerConsumerQueue) at
- address "pcq" has been created. The ANNOTATE_PCQ_* annotations
- should be used only for FIFO queues. For non-FIFO queues use
- ANNOTATE_HAPPENS_BEFORE (for put) and ANNOTATE_HAPPENS_AFTER (for get). */
- #define ANNOTATE_PCQ_CREATE(pcq) \
- AnnotatePCQCreate(__FILE__, __LINE__, pcq)
-
- /* Report that the queue at address "pcq" is about to be destroyed. */
- #define ANNOTATE_PCQ_DESTROY(pcq) \
- AnnotatePCQDestroy(__FILE__, __LINE__, pcq)
-
- /* Report that we are about to put an element into a FIFO queue at address
- "pcq". */
- #define ANNOTATE_PCQ_PUT(pcq) \
- AnnotatePCQPut(__FILE__, __LINE__, pcq)
-
- /* Report that we've just got an element from a FIFO queue at address "pcq". */
- #define ANNOTATE_PCQ_GET(pcq) \
- AnnotatePCQGet(__FILE__, __LINE__, pcq)
-
- /* -------------------------------------------------------------
- Annotations that suppress errors. It is usually better to express the
- program's synchronization using the other annotations, but these can
- be used when all else fails. */
-
- /* Report that we may have a benign race at "pointer", with size
- "sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the
- point where "pointer" has been allocated, preferably close to the point
- where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC. */
- #define ANNOTATE_BENIGN_RACE(pointer, description) \
- AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \
- sizeof(*(pointer)), description)
-
- /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
- the memory range [address, address+size). */
- #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
- AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
-
- /* Request the analysis tool to ignore all reads in the current thread
- until ANNOTATE_IGNORE_READS_END is called.
- Useful to ignore intentional racey reads, while still checking
- other reads and all writes.
- See also ANNOTATE_UNPROTECTED_READ. */
- #define ANNOTATE_IGNORE_READS_BEGIN() \
- AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
-
- /* Stop ignoring reads. */
- #define ANNOTATE_IGNORE_READS_END() \
- AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
-
- /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */
- #define ANNOTATE_IGNORE_WRITES_BEGIN() \
- AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
-
- /* Stop ignoring writes. */
- #define ANNOTATE_IGNORE_WRITES_END() \
- AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
-
- /* Start ignoring all memory accesses (reads and writes). */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
- do {\
- ANNOTATE_IGNORE_READS_BEGIN();\
- ANNOTATE_IGNORE_WRITES_BEGIN();\
- }while(0)\
-
- /* Stop ignoring all memory accesses. */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
- do {\
- ANNOTATE_IGNORE_WRITES_END();\
- ANNOTATE_IGNORE_READS_END();\
- }while(0)\
-
- /* Enable (enable!=0) or disable (enable==0) race detection for all threads.
- This annotation could be useful if you want to skip expensive race analysis
- during some period of program execution, e.g. during initialization. */
- #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
- AnnotateEnableRaceDetection(__FILE__, __LINE__, enable)
-
- /* -------------------------------------------------------------
- Annotations useful for debugging. */
-
- /* Request to trace every access to "address". */
- #define ANNOTATE_TRACE_MEMORY(address) \
- AnnotateTraceMemory(__FILE__, __LINE__, address)
-
- /* Report the current thread name to a race detector. */
- #define ANNOTATE_THREAD_NAME(name) \
- AnnotateThreadName(__FILE__, __LINE__, name)
-
- /* -------------------------------------------------------------
- Annotations useful when implementing locks. They are not
- normally needed by modules that merely use locks.
- The "lock" argument is a pointer to the lock object. */
-
- /* Report that a lock has been created at address "lock". */
- #define ANNOTATE_RWLOCK_CREATE(lock) \
- AnnotateRWLockCreate(__FILE__, __LINE__, lock)
-
- /* Report that the lock at address "lock" is about to be destroyed. */
- #define ANNOTATE_RWLOCK_DESTROY(lock) \
- AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
-
- /* Report that the lock at address "lock" has been acquired.
- is_w=1 for writer lock, is_w=0 for reader lock. */
- #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
- AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
-
- /* Report that the lock at address "lock" is about to be released. */
- #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
- AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
-
- /* -------------------------------------------------------------
- Annotations useful when implementing barriers. They are not
- normally needed by modules that merely use barriers.
- The "barrier" argument is a pointer to the barrier object. */
-
- /* Report that the "barrier" has been initialized with initial "count".
- If 'reinitialization_allowed' is true, initialization is allowed to happen
- multiple times w/o calling barrier_destroy() */
- #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
- AnnotateBarrierInit(__FILE__, __LINE__, barrier, count, \
- reinitialization_allowed)
-
- /* Report that we are about to enter barrier_wait("barrier"). */
- #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \
- AnnotateBarrierWaitBefore(__FILE__, __LINE__, barrier)
-
- /* Report that we just exited barrier_wait("barrier"). */
- #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \
- AnnotateBarrierWaitAfter(__FILE__, __LINE__, barrier)
-
- /* Report that the "barrier" has been destroyed. */
- #define ANNOTATE_BARRIER_DESTROY(barrier) \
- AnnotateBarrierDestroy(__FILE__, __LINE__, barrier)
-
- /* -------------------------------------------------------------
- Annotations useful for testing race detectors. */
-
- /* Report that we expect a race on the variable at "address".
- Use only in unit tests for a race detector. */
- #define ANNOTATE_EXPECT_RACE(address, description) \
- AnnotateExpectRace(__FILE__, __LINE__, address, description)
-
- /* A no-op. Insert where you like to test the interceptors. */
- #define ANNOTATE_NO_OP(arg) \
- AnnotateNoOp(__FILE__, __LINE__, arg)
-
- /* Force the race detector to flush its state. The actual effect depends on
- * the implementation of the detector. */
- #define ANNOTATE_FLUSH_STATE() \
- AnnotateFlushState(__FILE__, __LINE__)
-
-
-#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
-
- #define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
- #define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
- #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
- #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
- #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) /* */
- #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) /* empty */
- #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) /* empty */
- #define ANNOTATE_BARRIER_DESTROY(barrier) /* empty */
- #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) /* empty */
- #define ANNOTATE_CONDVAR_WAIT(cv) /* empty */
- #define ANNOTATE_CONDVAR_SIGNAL(cv) /* empty */
- #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) /* empty */
- #define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
- #define ANNOTATE_HAPPENS_AFTER(obj) /* empty */
- #define ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) /* empty */
- #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(address, size) /* empty */
- #define ANNOTATE_SWAP_MEMORY_RANGE(address, size) /* empty */
- #define ANNOTATE_PCQ_CREATE(pcq) /* empty */
- #define ANNOTATE_PCQ_DESTROY(pcq) /* empty */
- #define ANNOTATE_PCQ_PUT(pcq) /* empty */
- #define ANNOTATE_PCQ_GET(pcq) /* empty */
- #define ANNOTATE_NEW_MEMORY(address, size) /* empty */
- #define ANNOTATE_EXPECT_RACE(address, description) /* empty */
- #define ANNOTATE_BENIGN_RACE(address, description) /* empty */
- #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
- #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) /* empty */
- #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) /* empty */
- #define ANNOTATE_TRACE_MEMORY(arg) /* empty */
- #define ANNOTATE_THREAD_NAME(name) /* empty */
- #define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_READS_END() /* empty */
- #define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_WRITES_END() /* empty */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
- #define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
- #define ANNOTATE_NO_OP(arg) /* empty */
- #define ANNOTATE_FLUSH_STATE() /* empty */
-
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
-
-/* Macro definitions for GCC attributes that allow static thread safety
- analysis to recognize and use some of the dynamic annotations as
- escape hatches.
- TODO(lcwu): remove the check for __SUPPORT_DYN_ANNOTATION__ once the
- default crosstool/GCC supports these GCC attributes. */
-
-#define ANNOTALYSIS_STATIC_INLINE
-#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY ;
-#define ANNOTALYSIS_IGNORE_READS_BEGIN
-#define ANNOTALYSIS_IGNORE_READS_END
-#define ANNOTALYSIS_IGNORE_WRITES_BEGIN
-#define ANNOTALYSIS_IGNORE_WRITES_END
-#define ANNOTALYSIS_UNPROTECTED_READ
-
-#if defined(__GNUC__) && (!defined(SWIG)) && (!defined(__clang__)) && \
- defined(__SUPPORT_TS_ANNOTATION__) && defined(__SUPPORT_DYN_ANNOTATION__)
-
-#if DYNAMIC_ANNOTATIONS_ENABLED == 0
-#define ANNOTALYSIS_ONLY 1
-#undef ANNOTALYSIS_STATIC_INLINE
-#define ANNOTALYSIS_STATIC_INLINE static inline
-#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY { (void)file; (void)line; }
-#endif
-
-/* Only emit attributes when annotalysis is enabled. */
-#if defined(__SUPPORT_TS_ANNOTATION__) && defined(__SUPPORT_DYN_ANNOTATION__)
-#undef ANNOTALYSIS_IGNORE_READS_BEGIN
-#define ANNOTALYSIS_IGNORE_READS_BEGIN __attribute__ ((ignore_reads_begin))
-#undef ANNOTALYSIS_IGNORE_READS_END
-#define ANNOTALYSIS_IGNORE_READS_END __attribute__ ((ignore_reads_end))
-#undef ANNOTALYSIS_IGNORE_WRITES_BEGIN
-#define ANNOTALYSIS_IGNORE_WRITES_BEGIN __attribute__ ((ignore_writes_begin))
-#undef ANNOTALYSIS_IGNORE_WRITES_END
-#define ANNOTALYSIS_IGNORE_WRITES_END __attribute__ ((ignore_writes_end))
-#undef ANNOTALYSIS_UNPROTECTED_READ
-#define ANNOTALYSIS_UNPROTECTED_READ __attribute__ ((unprotected_read))
-#endif
-
-#endif // defined(__GNUC__) && (!defined(SWIG)) && (!defined(__clang__))
-
-/* Use the macros above rather than using these functions directly. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-void AnnotateRWLockCreate(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockDestroy(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockAcquired(const char *file, int line,
- const volatile void *lock, long is_w);
-void AnnotateRWLockReleased(const char *file, int line,
- const volatile void *lock, long is_w);
-void AnnotateBarrierInit(const char *file, int line,
- const volatile void *barrier, long count,
- long reinitialization_allowed);
-void AnnotateBarrierWaitBefore(const char *file, int line,
- const volatile void *barrier);
-void AnnotateBarrierWaitAfter(const char *file, int line,
- const volatile void *barrier);
-void AnnotateBarrierDestroy(const char *file, int line,
- const volatile void *barrier);
-void AnnotateCondVarWait(const char *file, int line,
- const volatile void *cv,
- const volatile void *lock);
-void AnnotateCondVarSignal(const char *file, int line,
- const volatile void *cv);
-void AnnotateCondVarSignalAll(const char *file, int line,
- const volatile void *cv);
-void AnnotatePublishMemoryRange(const char *file, int line,
- const volatile void *address,
- long size);
-void AnnotateUnpublishMemoryRange(const char *file, int line,
- const volatile void *address,
- long size);
-void AnnotatePCQCreate(const char *file, int line,
- const volatile void *pcq);
-void AnnotatePCQDestroy(const char *file, int line,
- const volatile void *pcq);
-void AnnotatePCQPut(const char *file, int line,
- const volatile void *pcq);
-void AnnotatePCQGet(const char *file, int line,
- const volatile void *pcq);
-void AnnotateNewMemory(const char *file, int line,
- const volatile void *address,
- long size);
-void AnnotateExpectRace(const char *file, int line,
- const volatile void *address,
- const char *description);
-void AnnotateBenignRace(const char *file, int line,
- const volatile void *address,
- const char *description);
-void AnnotateBenignRaceSized(const char *file, int line,
- const volatile void *address,
- long size,
- const char *description);
-void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
- const volatile void *mu);
-void AnnotateTraceMemory(const char *file, int line,
- const volatile void *arg);
-void AnnotateThreadName(const char *file, int line,
- const char *name);
-ANNOTALYSIS_STATIC_INLINE
-void AnnotateIgnoreReadsBegin(const char *file, int line)
- ANNOTALYSIS_IGNORE_READS_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-ANNOTALYSIS_STATIC_INLINE
-void AnnotateIgnoreReadsEnd(const char *file, int line)
- ANNOTALYSIS_IGNORE_READS_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-ANNOTALYSIS_STATIC_INLINE
-void AnnotateIgnoreWritesBegin(const char *file, int line)
- ANNOTALYSIS_IGNORE_WRITES_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-ANNOTALYSIS_STATIC_INLINE
-void AnnotateIgnoreWritesEnd(const char *file, int line)
- ANNOTALYSIS_IGNORE_WRITES_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-void AnnotateEnableRaceDetection(const char *file, int line, int enable);
-void AnnotateNoOp(const char *file, int line,
- const volatile void *arg);
-void AnnotateFlushState(const char *file, int line);
-
-/* Return non-zero value if running under valgrind.
-
- If "valgrind.h" is included into dynamic_annotations.c,
- the regular valgrind mechanism will be used.
- See http://valgrind.org/docs/manual/manual-core-adv.html about
- RUNNING_ON_VALGRIND and other valgrind "client requests".
- The file "valgrind.h" may be obtained by doing
- svn co svn://svn.valgrind.org/valgrind/trunk/include
-
- If for some reason you can't use "valgrind.h" or want to fake valgrind,
- there are two ways to make this function return non-zero:
- - Use environment variable: export RUNNING_ON_VALGRIND=1
- - Make your tool intercept the function RunningOnValgrind() and
- change its return value.
- */
-int RunningOnValgrind(void);
-
-/* ValgrindSlowdown returns:
- * 1.0, if (RunningOnValgrind() == 0)
- * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == NULL)
- * atof(getenv("VALGRIND_SLOWDOWN")) otherwise
- This function can be used to scale timeout values:
- EXAMPLE:
- for (;;) {
- DoExpensiveBackgroundTask();
- SleepForSeconds(5 * ValgrindSlowdown());
- }
- */
-double ValgrindSlowdown(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
-
- /* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
-
- Instead of doing
- ANNOTATE_IGNORE_READS_BEGIN();
- ... = x;
- ANNOTATE_IGNORE_READS_END();
- one can use
- ... = ANNOTATE_UNPROTECTED_READ(x); */
- template <class T>
- inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
- ANNOTALYSIS_UNPROTECTED_READ {
- ANNOTATE_IGNORE_READS_BEGIN();
- T res = x;
- ANNOTATE_IGNORE_READS_END();
- return res;
- }
- /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
- #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
- namespace { \
- class static_var ## _annotator { \
- public: \
- static_var ## _annotator() { \
- ANNOTATE_BENIGN_RACE_SIZED(&static_var, \
- sizeof(static_var), \
- # static_var ": " description); \
- } \
- }; \
- static static_var ## _annotator the ## static_var ## _annotator;\
- }
-#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
-
- #define ANNOTATE_UNPROTECTED_READ(x) (x)
- #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */
-
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
-
-/* Annotalysis, a GCC based static analyzer, is able to understand and use
- some of the dynamic annotations defined in this file. However, dynamic
- annotations are usually disabled in the opt mode (to avoid additional
- runtime overheads) while Annotalysis only works in the opt mode.
- In order for Annotalysis to use these dynamic annotations when they
- are disabled, we re-define these annotations here. Note that unlike the
- original macro definitions above, these macros are expanded to calls to
- static inline functions so that the compiler will be able to remove the
- calls after the analysis. */
-
-#ifdef ANNOTALYSIS_ONLY
-
- #undef ANNOTALYSIS_ONLY
-
- /* Undefine and re-define the macros that the static analyzer understands. */
- #undef ANNOTATE_IGNORE_READS_BEGIN
- #define ANNOTATE_IGNORE_READS_BEGIN() \
- AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
-
- #undef ANNOTATE_IGNORE_READS_END
- #define ANNOTATE_IGNORE_READS_END() \
- AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
-
- #undef ANNOTATE_IGNORE_WRITES_BEGIN
- #define ANNOTATE_IGNORE_WRITES_BEGIN() \
- AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
-
- #undef ANNOTATE_IGNORE_WRITES_END
- #define ANNOTATE_IGNORE_WRITES_END() \
- AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
-
- #undef ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
- do { \
- ANNOTATE_IGNORE_READS_BEGIN(); \
- ANNOTATE_IGNORE_WRITES_BEGIN(); \
- }while(0) \
-
- #undef ANNOTATE_IGNORE_READS_AND_WRITES_END
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
- do { \
- ANNOTATE_IGNORE_WRITES_END(); \
- ANNOTATE_IGNORE_READS_END(); \
- }while(0) \
-
- #if defined(__cplusplus)
- #undef ANNOTATE_UNPROTECTED_READ
- template <class T>
- inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
- ANNOTALYSIS_UNPROTECTED_READ {
- ANNOTATE_IGNORE_READS_BEGIN();
- T res = x;
- ANNOTATE_IGNORE_READS_END();
- return res;
- }
- #endif /* __cplusplus */
-
-#endif /* ANNOTALYSIS_ONLY */
-
-/* Undefine the macros intended only in this file. */
-#undef ANNOTALYSIS_STATIC_INLINE
-#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
-
-#endif /* BASE_DYNAMIC_ANNOTATIONS_H_ */
diff --git a/src/third_party/gperftools-2.5/src/base/elf_mem_image.cc b/src/third_party/gperftools-2.5/src/base/elf_mem_image.cc
deleted file mode 100644
index d2ca1a5e131..00000000000
--- a/src/third_party/gperftools-2.5/src/base/elf_mem_image.cc
+++ /dev/null
@@ -1,434 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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 <stddef.h> // for size_t, ptrdiff_t
-#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/src/third_party/gperftools-2.5/src/base/elf_mem_image.h b/src/third_party/gperftools-2.5/src/base/elf_mem_image.h
deleted file mode 100644
index 5fb00fffb5f..00000000000
--- a/src/third_party/gperftools-2.5/src/base/elf_mem_image.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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/src/third_party/gperftools-2.5/src/base/elfcore.h b/src/third_party/gperftools-2.5/src/base/elfcore.h
deleted file mode 100644
index d9599edac8d..00000000000
--- a/src/third_party/gperftools-2.5/src/base/elfcore.h
+++ /dev/null
@@ -1,401 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2005-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: Markus Gutschke, Carl Crous
- */
-
-#ifndef _ELFCORE_H
-#define _ELFCORE_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* We currently only support x86-32, x86-64, ARM, MIPS, PPC on Linux.
- * Porting to other related platforms should not be difficult.
- */
-#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
- defined(__mips__) || defined(__PPC__)) && defined(__linux)
-
-#include <stdarg.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <config.h>
-
-
-/* Define the DUMPER symbol to make sure that there is exactly one
- * core dumper built into the library.
- */
-#define DUMPER "ELF"
-
-/* By the time that we get a chance to read CPU registers in the
- * calling thread, they are already in a not particularly useful
- * state. Besides, there will be multiple frames on the stack that are
- * just making the core file confusing. To fix this problem, we take a
- * snapshot of the frame pointer, stack pointer, and instruction
- * pointer at an earlier time, and then insert these values into the
- * core file.
- */
-
-#if defined(__i386__) || defined(__x86_64__)
- typedef struct i386_regs { /* Normal (non-FPU) CPU registers */
- #ifdef __x86_64__
- #define BP rbp
- #define SP rsp
- #define IP rip
- uint64_t r15,r14,r13,r12,rbp,rbx,r11,r10;
- uint64_t r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax;
- uint64_t rip,cs,eflags;
- uint64_t rsp,ss;
- uint64_t fs_base, gs_base;
- uint64_t ds,es,fs,gs;
- #else
- #define BP ebp
- #define SP esp
- #define IP eip
- uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
- uint16_t ds, __ds, es, __es;
- uint16_t fs, __fs, gs, __gs;
- uint32_t orig_eax, eip;
- uint16_t cs, __cs;
- uint32_t eflags, esp;
- uint16_t ss, __ss;
- #endif
- } i386_regs;
-#elif defined(__ARM_ARCH_3__)
- typedef struct arm_regs { /* General purpose registers */
- #define BP uregs[11] /* Frame pointer */
- #define SP uregs[13] /* Stack pointer */
- #define IP uregs[15] /* Program counter */
- #define LR uregs[14] /* Link register */
- long uregs[18];
- } arm_regs;
-#elif defined(__mips__)
- typedef struct mips_regs {
- unsigned long pad[6]; /* Unused padding to match kernel structures */
- unsigned long uregs[32]; /* General purpose registers. */
- unsigned long hi; /* Used for multiplication and division. */
- unsigned long lo;
- unsigned long cp0_epc; /* Program counter. */
- unsigned long cp0_badvaddr;
- unsigned long cp0_status;
- unsigned long cp0_cause;
- unsigned long unused;
- } mips_regs;
-#elif defined (__PPC__)
- typedef struct ppc_regs {
- #define SP uregs[1] /* Stack pointer */
- #define IP rip /* Program counter */
- #define LR lr /* Link register */
- unsigned long uregs[32]; /* General Purpose Registers - r0-r31. */
- double fpr[32]; /* Floating-Point Registers - f0-f31. */
- unsigned long rip; /* Program counter. */
- unsigned long msr;
- unsigned long ccr;
- unsigned long lr;
- unsigned long ctr;
- unsigned long xeq;
- unsigned long mq;
- } ppc_regs;
-#endif
-
-#if defined(__i386__) && defined(__GNUC__)
- /* On x86 we provide an optimized version of the FRAME() macro, if the
- * compiler supports a GCC-style asm() directive. This results in somewhat
- * more accurate values for CPU registers.
- */
- typedef struct Frame {
- struct i386_regs uregs;
- int errno_;
- pid_t tid;
- } Frame;
- #define FRAME(f) Frame f; \
- do { \
- f.errno_ = errno; \
- f.tid = sys_gettid(); \
- __asm__ volatile ( \
- "push %%ebp\n" \
- "push %%ebx\n" \
- "mov %%ebx,0(%%eax)\n" \
- "mov %%ecx,4(%%eax)\n" \
- "mov %%edx,8(%%eax)\n" \
- "mov %%esi,12(%%eax)\n" \
- "mov %%edi,16(%%eax)\n" \
- "mov %%ebp,20(%%eax)\n" \
- "mov %%eax,24(%%eax)\n" \
- "mov %%ds,%%ebx\n" \
- "mov %%ebx,28(%%eax)\n" \
- "mov %%es,%%ebx\n" \
- "mov %%ebx,32(%%eax)\n" \
- "mov %%fs,%%ebx\n" \
- "mov %%ebx,36(%%eax)\n" \
- "mov %%gs,%%ebx\n" \
- "mov %%ebx, 40(%%eax)\n" \
- "call 0f\n" \
- "0:pop %%ebx\n" \
- "add $1f-0b,%%ebx\n" \
- "mov %%ebx,48(%%eax)\n" \
- "mov %%cs,%%ebx\n" \
- "mov %%ebx,52(%%eax)\n" \
- "pushf\n" \
- "pop %%ebx\n" \
- "mov %%ebx,56(%%eax)\n" \
- "mov %%esp,%%ebx\n" \
- "add $8,%%ebx\n" \
- "mov %%ebx,60(%%eax)\n" \
- "mov %%ss,%%ebx\n" \
- "mov %%ebx,64(%%eax)\n" \
- "pop %%ebx\n" \
- "pop %%ebp\n" \
- "1:" \
- : : "a" (&f) : "memory"); \
- } while (0)
- #define SET_FRAME(f,r) \
- do { \
- errno = (f).errno_; \
- (r) = (f).uregs; \
- } while (0)
-#elif defined(__x86_64__) && defined(__GNUC__)
- /* The FRAME and SET_FRAME macros for x86_64. */
- typedef struct Frame {
- struct i386_regs uregs;
- int errno_;
- pid_t tid;
- } Frame;
- #define FRAME(f) Frame f; \
- do { \
- f.errno_ = errno; \
- f.tid = sys_gettid(); \
- __asm__ volatile ( \
- "push %%rbp\n" \
- "push %%rbx\n" \
- "mov %%r15,0(%%rax)\n" \
- "mov %%r14,8(%%rax)\n" \
- "mov %%r13,16(%%rax)\n" \
- "mov %%r12,24(%%rax)\n" \
- "mov %%rbp,32(%%rax)\n" \
- "mov %%rbx,40(%%rax)\n" \
- "mov %%r11,48(%%rax)\n" \
- "mov %%r10,56(%%rax)\n" \
- "mov %%r9,64(%%rax)\n" \
- "mov %%r8,72(%%rax)\n" \
- "mov %%rax,80(%%rax)\n" \
- "mov %%rcx,88(%%rax)\n" \
- "mov %%rdx,96(%%rax)\n" \
- "mov %%rsi,104(%%rax)\n" \
- "mov %%rdi,112(%%rax)\n" \
- "mov %%ds,%%rbx\n" \
- "mov %%rbx,184(%%rax)\n" \
- "mov %%es,%%rbx\n" \
- "mov %%rbx,192(%%rax)\n" \
- "mov %%fs,%%rbx\n" \
- "mov %%rbx,200(%%rax)\n" \
- "mov %%gs,%%rbx\n" \
- "mov %%rbx,208(%%rax)\n" \
- "call 0f\n" \
- "0:pop %%rbx\n" \
- "add $1f-0b,%%rbx\n" \
- "mov %%rbx,128(%%rax)\n" \
- "mov %%cs,%%rbx\n" \
- "mov %%rbx,136(%%rax)\n" \
- "pushf\n" \
- "pop %%rbx\n" \
- "mov %%rbx,144(%%rax)\n" \
- "mov %%rsp,%%rbx\n" \
- "add $16,%%ebx\n" \
- "mov %%rbx,152(%%rax)\n" \
- "mov %%ss,%%rbx\n" \
- "mov %%rbx,160(%%rax)\n" \
- "pop %%rbx\n" \
- "pop %%rbp\n" \
- "1:" \
- : : "a" (&f) : "memory"); \
- } while (0)
- #define SET_FRAME(f,r) \
- do { \
- errno = (f).errno_; \
- (f).uregs.fs_base = (r).fs_base; \
- (f).uregs.gs_base = (r).gs_base; \
- (r) = (f).uregs; \
- } while (0)
-#elif defined(__ARM_ARCH_3__) && defined(__GNUC__)
- /* ARM calling conventions are a little more tricky. A little assembly
- * helps in obtaining an accurate snapshot of all registers.
- */
- typedef struct Frame {
- struct arm_regs arm;
- int errno_;
- pid_t tid;
- } Frame;
- #define FRAME(f) Frame f; \
- do { \
- long cpsr; \
- f.errno_ = errno; \
- f.tid = sys_gettid(); \
- __asm__ volatile( \
- "stmia %0, {r0-r15}\n" /* All integer regs */\
- : : "r"(&f.arm) : "memory"); \
- f.arm.uregs[16] = 0; \
- __asm__ volatile( \
- "mrs %0, cpsr\n" /* Condition code reg */\
- : "=r"(cpsr)); \
- f.arm.uregs[17] = cpsr; \
- } while (0)
- #define SET_FRAME(f,r) \
- do { \
- /* Don't override the FPU status register. */\
- /* Use the value obtained from ptrace(). This*/\
- /* works, because our code does not perform */\
- /* any FPU operations, itself. */\
- long fps = (f).arm.uregs[16]; \
- errno = (f).errno_; \
- (r) = (f).arm; \
- (r).uregs[16] = fps; \
- } while (0)
-#elif defined(__mips__) && defined(__GNUC__)
- typedef struct Frame {
- struct mips_regs mips_regs;
- int errno_;
- pid_t tid;
- } Frame;
- #define MIPSREG(n) ({ register unsigned long r __asm__("$"#n); r; })
- #define FRAME(f) Frame f = { 0 }; \
- do { \
- unsigned long hi, lo; \
- register unsigned long pc __asm__("$31"); \
- f.mips_regs.uregs[ 0] = MIPSREG( 0); \
- f.mips_regs.uregs[ 1] = MIPSREG( 1); \
- f.mips_regs.uregs[ 2] = MIPSREG( 2); \
- f.mips_regs.uregs[ 3] = MIPSREG( 3); \
- f.mips_regs.uregs[ 4] = MIPSREG( 4); \
- f.mips_regs.uregs[ 5] = MIPSREG( 5); \
- f.mips_regs.uregs[ 6] = MIPSREG( 6); \
- f.mips_regs.uregs[ 7] = MIPSREG( 7); \
- f.mips_regs.uregs[ 8] = MIPSREG( 8); \
- f.mips_regs.uregs[ 9] = MIPSREG( 9); \
- f.mips_regs.uregs[10] = MIPSREG(10); \
- f.mips_regs.uregs[11] = MIPSREG(11); \
- f.mips_regs.uregs[12] = MIPSREG(12); \
- f.mips_regs.uregs[13] = MIPSREG(13); \
- f.mips_regs.uregs[14] = MIPSREG(14); \
- f.mips_regs.uregs[15] = MIPSREG(15); \
- f.mips_regs.uregs[16] = MIPSREG(16); \
- f.mips_regs.uregs[17] = MIPSREG(17); \
- f.mips_regs.uregs[18] = MIPSREG(18); \
- f.mips_regs.uregs[19] = MIPSREG(19); \
- f.mips_regs.uregs[20] = MIPSREG(20); \
- f.mips_regs.uregs[21] = MIPSREG(21); \
- f.mips_regs.uregs[22] = MIPSREG(22); \
- f.mips_regs.uregs[23] = MIPSREG(23); \
- f.mips_regs.uregs[24] = MIPSREG(24); \
- f.mips_regs.uregs[25] = MIPSREG(25); \
- f.mips_regs.uregs[26] = MIPSREG(26); \
- f.mips_regs.uregs[27] = MIPSREG(27); \
- f.mips_regs.uregs[28] = MIPSREG(28); \
- f.mips_regs.uregs[29] = MIPSREG(29); \
- f.mips_regs.uregs[30] = MIPSREG(30); \
- f.mips_regs.uregs[31] = MIPSREG(31); \
- __asm__ volatile ("mfhi %0" : "=r"(hi)); \
- __asm__ volatile ("mflo %0" : "=r"(lo)); \
- __asm__ volatile ("jal 1f; 1:nop" : "=r"(pc)); \
- f.mips_regs.hi = hi; \
- f.mips_regs.lo = lo; \
- f.mips_regs.cp0_epc = pc; \
- f.errno_ = errno; \
- f.tid = sys_gettid(); \
- } while (0)
- #define SET_FRAME(f,r) \
- do { \
- errno = (f).errno_; \
- memcpy((r).uregs, (f).mips_regs.uregs, \
- 32*sizeof(unsigned long)); \
- (r).hi = (f).mips_regs.hi; \
- (r).lo = (f).mips_regs.lo; \
- (r).cp0_epc = (f).mips_regs.cp0_epc; \
- } while (0)
-#else
- /* If we do not have a hand-optimized assembly version of the FRAME()
- * macro, we cannot reliably unroll the stack. So, we show a few additional
- * stack frames for the coredumper.
- */
- typedef struct Frame {
- pid_t tid;
- } Frame;
- #define FRAME(f) Frame f; do { f.tid = sys_gettid(); } while (0)
- #define SET_FRAME(f,r) do { } while (0)
-#endif
-
-
-/* Internal function for generating a core file. This API can change without
- * notice and is only supposed to be used internally by the core dumper.
- *
- * This function works for both single- and multi-threaded core
- * dumps. If called as
- *
- * FRAME(frame);
- * InternalGetCoreDump(&frame, 0, NULL, ap);
- *
- * it creates a core file that only contains information about the
- * calling thread.
- *
- * Optionally, the caller can provide information about other threads
- * by passing their process ids in "thread_pids". The process id of
- * the caller should not be included in this array. All of the threads
- * must have been attached to with ptrace(), prior to calling this
- * function. They will be detached when "InternalGetCoreDump()" returns.
- *
- * This function either returns a file handle that can be read for obtaining
- * a core dump, or "-1" in case of an error. In the latter case, "errno"
- * will be set appropriately.
- *
- * While "InternalGetCoreDump()" is not technically async signal safe, you
- * might be tempted to invoke it from a signal handler. The code goes to
- * great lengths to make a best effort that this will actually work. But in
- * any case, you must make sure that you preserve the value of "errno"
- * yourself. It is guaranteed to be clobbered otherwise.
- *
- * Also, "InternalGetCoreDump" is not strictly speaking re-entrant. Again,
- * it makes a best effort to behave reasonably when called in a multi-
- * threaded environment, but it is ultimately the caller's responsibility
- * to provide locking.
- */
-int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids,
- va_list ap
- /* const struct CoreDumpParameters *params,
- const char *file_name,
- const char *PATH
- */);
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* _ELFCORE_H */
diff --git a/src/third_party/gperftools-2.5/src/base/googleinit.h b/src/third_party/gperftools-2.5/src/base/googleinit.h
deleted file mode 100644
index 3ea411a325a..00000000000
--- a/src/third_party/gperftools-2.5/src/base/googleinit.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Jacob Hoffman-Andrews
-
-#ifndef _GOOGLEINIT_H
-#define _GOOGLEINIT_H
-
-#include "base/logging.h"
-
-class GoogleInitializer {
- public:
- typedef void (*VoidFunction)(void);
- GoogleInitializer(const char* name, VoidFunction ctor, VoidFunction dtor)
- : name_(name), destructor_(dtor) {
- RAW_VLOG(10, "<GoogleModuleObject> constructing: %s\n", name_);
- if (ctor)
- ctor();
- }
- ~GoogleInitializer() {
- RAW_VLOG(10, "<GoogleModuleObject> destroying: %s\n", name_);
- if (destructor_)
- destructor_();
- }
-
- private:
- const char* const name_;
- const VoidFunction destructor_;
-};
-
-#define REGISTER_MODULE_INITIALIZER(name, body) \
- namespace { \
- static void google_init_module_##name () { body; } \
- GoogleInitializer google_initializer_module_##name(#name, \
- google_init_module_##name, NULL); \
- }
-
-#define REGISTER_MODULE_DESTRUCTOR(name, body) \
- namespace { \
- static void google_destruct_module_##name () { body; } \
- GoogleInitializer google_destructor_module_##name(#name, \
- NULL, google_destruct_module_##name); \
- }
-
-
-#endif /* _GOOGLEINIT_H */
diff --git a/src/third_party/gperftools-2.5/src/base/linux_syscall_support.h b/src/third_party/gperftools-2.5/src/base/linux_syscall_support.h
deleted file mode 100644
index 5d578cd72dc..00000000000
--- a/src/third_party/gperftools-2.5/src/base/linux_syscall_support.h
+++ /dev/null
@@ -1,2755 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2005-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: Markus Gutschke
- */
-
-/* This file includes Linux-specific support functions common to the
- * coredumper and the thread lister; primarily, this is a collection
- * of direct system calls, and a couple of symbols missing from
- * standard header files.
- * There are a few options that the including file can set to control
- * the behavior of this file:
- *
- * SYS_CPLUSPLUS:
- * The entire header file will normally be wrapped in 'extern "C" { }",
- * making it suitable for compilation as both C and C++ source. If you
- * do not want to do this, you can set the SYS_CPLUSPLUS macro to inhibit
- * the wrapping. N.B. doing so will suppress inclusion of all prerequisite
- * system header files, too. It is the caller's responsibility to provide
- * the necessary definitions.
- *
- * SYS_ERRNO:
- * All system calls will update "errno" unless overriden by setting the
- * SYS_ERRNO macro prior to including this file. SYS_ERRNO should be
- * an l-value.
- *
- * SYS_INLINE:
- * New symbols will be defined "static inline", unless overridden by
- * the SYS_INLINE macro.
- *
- * SYS_LINUX_SYSCALL_SUPPORT_H
- * This macro is used to avoid multiple inclusions of this header file.
- * If you need to include this file more than once, make sure to
- * unset SYS_LINUX_SYSCALL_SUPPORT_H before each inclusion.
- *
- * SYS_PREFIX:
- * New system calls will have a prefix of "sys_" unless overridden by
- * the SYS_PREFIX macro. Valid values for this macro are [0..9] which
- * results in prefixes "sys[0..9]_". It is also possible to set this
- * macro to -1, which avoids all prefixes.
- *
- * This file defines a few internal symbols that all start with "LSS_".
- * Do not access these symbols from outside this file. They are not part
- * of the supported API.
- *
- * NOTE: This is a stripped down version of the official opensource
- * version of linux_syscall_support.h, which lives at
- * http://code.google.com/p/linux-syscall-support/
- * It includes only the syscalls that are used in perftools, plus a
- * few extra. Here's the breakdown:
- * 1) Perftools uses these: grep -rho 'sys_[a-z0-9_A-Z]* *(' src | sort -u
- * sys__exit(
- * sys_clone(
- * sys_close(
- * sys_fcntl(
- * sys_fstat(
- * sys_futex(
- * sys_getcpu(
- * sys_getdents64(
- * sys_getppid(
- * sys_gettid(
- * sys_lseek(
- * sys_mmap(
- * sys_mremap(
- * sys_munmap(
- * sys_open(
- * sys_pipe(
- * sys_prctl(
- * sys_ptrace(
- * sys_ptrace_detach(
- * sys_read(
- * sys_sched_yield(
- * sys_sigaction(
- * sys_sigaltstack(
- * sys_sigdelset(
- * sys_sigfillset(
- * sys_sigprocmask(
- * sys_socket(
- * sys_stat(
- * sys_waitpid(
- * 2) These are used as subroutines of the above:
- * sys_getpid -- gettid
- * sys_kill -- ptrace_detach
- * sys_restore -- sigaction
- * sys_restore_rt -- sigaction
- * sys_socketcall -- socket
- * sys_wait4 -- waitpid
- * 3) I left these in even though they're not used. They either
- * complement the above (write vs read) or are variants (rt_sigaction):
- * sys_fstat64
- * sys_llseek
- * sys_mmap2
- * sys_openat
- * sys_getdents
- * sys_rt_sigaction
- * sys_rt_sigprocmask
- * sys_sigaddset
- * sys_sigemptyset
- * sys_stat64
- * sys_write
- */
-#ifndef SYS_LINUX_SYSCALL_SUPPORT_H
-#define SYS_LINUX_SYSCALL_SUPPORT_H
-
-/* We currently only support x86-32, x86-64, ARM, MIPS, PPC/PPC64, Aarch64 and s390x on Linux.
- * Porting to other related platforms should not be difficult.
- */
-#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
- defined(__mips__) || defined(__PPC__) || \
- defined(__aarch64__) || defined(__s390x__)) \
- && (defined(__linux))
-
-#ifndef SYS_CPLUSPLUS
-#ifdef __cplusplus
-/* Some system header files in older versions of gcc neglect to properly
- * handle being included from C++. As it appears to be harmless to have
- * multiple nested 'extern "C"' blocks, just add another one here.
- */
-extern "C" {
-#endif
-
-#include <errno.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/ptrace.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <syscall.h>
-#include <unistd.h>
-#include <linux/unistd.h>
-#include <endian.h>
-
-#ifdef __mips__
-/* Include definitions of the ABI currently in use. */
-#include <sgidefs.h>
-#endif
-
-#endif
-
-/* As glibc often provides subtly incompatible data structures (and implicit
- * wrapper functions that convert them), we provide our own kernel data
- * structures for use by the system calls.
- * These structures have been developed by using Linux 2.6.23 headers for
- * reference. Note though, we do not care about exact API compatibility
- * with the kernel, and in fact the kernel often does not have a single
- * API that works across architectures. Instead, we try to mimic the glibc
- * API where reasonable, and only guarantee ABI compatibility with the
- * kernel headers.
- * Most notably, here are a few changes that were made to the structures
- * defined by kernel headers:
- *
- * - we only define structures, but not symbolic names for kernel data
- * types. For the latter, we directly use the native C datatype
- * (i.e. "unsigned" instead of "mode_t").
- * - in a few cases, it is possible to define identical structures for
- * both 32bit (e.g. i386) and 64bit (e.g. x86-64) platforms by
- * standardizing on the 64bit version of the data types. In particular,
- * this means that we use "unsigned" where the 32bit headers say
- * "unsigned long".
- * - overall, we try to minimize the number of cases where we need to
- * conditionally define different structures.
- * - the "struct kernel_sigaction" class of structures have been
- * modified to more closely mimic glibc's API by introducing an
- * anonymous union for the function pointer.
- * - a small number of field names had to have an underscore appended to
- * them, because glibc defines a global macro by the same name.
- */
-
-/* include/linux/dirent.h */
-struct kernel_dirent64 {
- unsigned long long d_ino;
- long long d_off;
- unsigned short d_reclen;
- unsigned char d_type;
- char d_name[256];
-};
-
-/* include/linux/dirent.h */
-struct kernel_dirent {
- long d_ino;
- long d_off;
- unsigned short d_reclen;
- char d_name[256];
-};
-
-/* include/linux/time.h */
-struct kernel_timespec {
- long tv_sec;
- long tv_nsec;
-};
-
-/* include/linux/time.h */
-struct kernel_timeval {
- long tv_sec;
- long tv_usec;
-};
-
-/* include/linux/resource.h */
-struct kernel_rusage {
- struct kernel_timeval ru_utime;
- struct kernel_timeval ru_stime;
- long ru_maxrss;
- long ru_ixrss;
- long ru_idrss;
- long ru_isrss;
- long ru_minflt;
- long ru_majflt;
- long ru_nswap;
- long ru_inblock;
- long ru_oublock;
- long ru_msgsnd;
- long ru_msgrcv;
- long ru_nsignals;
- long ru_nvcsw;
- long ru_nivcsw;
-};
-
-#if defined(__i386__) || defined(__arm__) || defined(__PPC__)
-
-/* include/asm-{arm,i386,mips,ppc}/signal.h */
-struct kernel_old_sigaction {
- union {
- void (*sa_handler_)(int);
- void (*sa_sigaction_)(int, siginfo_t *, void *);
- };
- unsigned long sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer)(void);
-} __attribute__((packed,aligned(4)));
-#elif (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
- #define kernel_old_sigaction kernel_sigaction
-#elif defined(__aarch64__) || defined(__s390x__)
- // No kernel_old_sigaction defined for arm64 or s390x.
-#endif
-
-/* Some kernel functions (e.g. sigaction() in 2.6.23) require that the
- * exactly match the size of the signal set, even though the API was
- * intended to be extensible. We define our own KERNEL_NSIG to deal with
- * this.
- * Please note that glibc provides signals [1.._NSIG-1], whereas the
- * kernel (and this header) provides the range [1..KERNEL_NSIG]. The
- * actual number of signals is obviously the same, but the constants
- * differ by one.
- */
-#ifdef __mips__
-#define KERNEL_NSIG 128
-#else
-#define KERNEL_NSIG 64
-#endif
-
-/* include/asm-{arm,i386,mips,x86_64}/signal.h */
-struct kernel_sigset_t {
- unsigned long sig[(KERNEL_NSIG + 8*sizeof(unsigned long) - 1)/
- (8*sizeof(unsigned long))];
-};
-
-/* include/asm-{arm,generic,i386,mips,x86_64,ppc}/signal.h */
-struct kernel_sigaction {
-#ifdef __mips__
- unsigned long sa_flags;
- union {
- void (*sa_handler_)(int);
- void (*sa_sigaction_)(int, siginfo_t *, void *);
- };
- struct kernel_sigset_t sa_mask;
-#else
- union {
- void (*sa_handler_)(int);
- void (*sa_sigaction_)(int, siginfo_t *, void *);
- };
- unsigned long sa_flags;
- void (*sa_restorer)(void);
- struct kernel_sigset_t sa_mask;
-#endif
-};
-
-/* include/asm-{arm,i386,mips,ppc}/stat.h */
-#ifdef __mips__
-#if _MIPS_SIM == _MIPS_SIM_ABI64
-struct kernel_stat {
-#else
-struct kernel_stat64 {
-#endif
- unsigned st_dev;
- unsigned __pad0[3];
- unsigned long long st_ino;
- unsigned st_mode;
- unsigned st_nlink;
- unsigned st_uid;
- unsigned st_gid;
- unsigned st_rdev;
- unsigned __pad1[3];
- long long st_size;
- unsigned st_atime_;
- unsigned st_atime_nsec_;
- unsigned st_mtime_;
- unsigned st_mtime_nsec_;
- unsigned st_ctime_;
- unsigned st_ctime_nsec_;
- unsigned st_blksize;
- unsigned __pad2;
- unsigned long long st_blocks;
-};
-#elif defined __PPC__
-struct kernel_stat64 {
- unsigned long long st_dev;
- unsigned long long st_ino;
- unsigned st_nlink;
- unsigned st_mode;
- unsigned st_uid;
- unsigned st_gid;
- int __pad2;
- unsigned long long st_rdev;
- long long st_size;
- long long st_blksize;
- long long st_blocks;
- kernel_timespec st_atim;
- kernel_timespec st_mtim;
- kernel_timespec st_ctim;
- unsigned long __unused4;
- unsigned long __unused5;
- unsigned long __unused6;
-};
-#else
-struct kernel_stat64 {
- unsigned long long st_dev;
- unsigned char __pad0[4];
- unsigned __st_ino;
- unsigned st_mode;
- unsigned st_nlink;
- unsigned st_uid;
- unsigned st_gid;
- unsigned long long st_rdev;
- unsigned char __pad3[4];
- long long st_size;
- unsigned st_blksize;
- unsigned long long st_blocks;
- unsigned st_atime_;
- unsigned st_atime_nsec_;
- unsigned st_mtime_;
- unsigned st_mtime_nsec_;
- unsigned st_ctime_;
- unsigned st_ctime_nsec_;
- unsigned long long st_ino;
-};
-#endif
-
-/* include/asm-{arm,generic,i386,mips,x86_64,ppc,s390}/stat.h */
-#if defined(__i386__) || defined(__arm__)
-struct kernel_stat {
- /* The kernel headers suggest that st_dev and st_rdev should be 32bit
- * quantities encoding 12bit major and 20bit minor numbers in an interleaved
- * format. In reality, we do not see useful data in the top bits. So,
- * we'll leave the padding in here, until we find a better solution.
- */
- unsigned short st_dev;
- short pad1;
- unsigned st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- short pad2;
- unsigned st_size;
- unsigned st_blksize;
- unsigned st_blocks;
- unsigned st_atime_;
- unsigned st_atime_nsec_;
- unsigned st_mtime_;
- unsigned st_mtime_nsec_;
- unsigned st_ctime_;
- unsigned st_ctime_nsec_;
- unsigned __unused4;
- unsigned __unused5;
-};
-#elif defined(__x86_64__)
-struct kernel_stat {
- uint64_t st_dev;
- uint64_t st_ino;
- uint64_t st_nlink;
- unsigned st_mode;
- unsigned st_uid;
- unsigned st_gid;
- unsigned __pad0;
- uint64_t st_rdev;
- int64_t st_size;
- int64_t st_blksize;
- int64_t st_blocks;
- uint64_t st_atime_;
- uint64_t st_atime_nsec_;
- uint64_t st_mtime_;
- uint64_t st_mtime_nsec_;
- uint64_t st_ctime_;
- uint64_t st_ctime_nsec_;
- int64_t __unused[3];
-};
-#elif defined(__PPC__)
-struct kernel_stat {
- unsigned long long st_dev;
- unsigned long st_ino;
- unsigned long st_nlink;
- unsigned long st_mode;
- unsigned st_uid;
- unsigned st_gid;
- int __pad2;
- unsigned long long st_rdev;
- long st_size;
- unsigned long st_blksize;
- unsigned long st_blocks;
- kernel_timespec st_atim;
- kernel_timespec st_mtim;
- kernel_timespec st_ctim;
- unsigned long __unused4;
- unsigned long __unused5;
- unsigned long __unused6;
-};
-#elif (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64)
-struct kernel_stat {
- unsigned st_dev;
- int st_pad1[3];
- unsigned st_ino;
- unsigned st_mode;
- unsigned st_nlink;
- unsigned st_uid;
- unsigned st_gid;
- unsigned st_rdev;
- int st_pad2[2];
- long st_size;
- int st_pad3;
- long st_atime_;
- long st_atime_nsec_;
- long st_mtime_;
- long st_mtime_nsec_;
- long st_ctime_;
- long st_ctime_nsec_;
- int st_blksize;
- int st_blocks;
- int st_pad4[14];
-};
-#elif defined(__aarch64__)
-struct kernel_stat {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned int st_mode;
- unsigned int st_nlink;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned long st_rdev;
- unsigned long __pad1;
- long st_size;
- int st_blksize;
- int __pad2;
- long st_blocks;
- long st_atime_;
- unsigned long st_atime_nsec_;
- long st_mtime_;
- unsigned long st_mtime_nsec_;
- long st_ctime_;
- unsigned long st_ctime_nsec_;
- unsigned int __unused4;
- unsigned int __unused5;
-};
-#elif defined(__s390x__)
-struct kernel_stat {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned long st_nlink;
- unsigned int st_mode;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned int __pad1;
- unsigned long st_rdev;
- unsigned long st_size;
- unsigned long st_atime_;
- unsigned long st_atime_nsec_;
- unsigned long st_mtime_;
- unsigned long st_mtime_nsec_;
- unsigned long st_ctime_;
- unsigned long st_ctime_nsec_;
- unsigned long st_blksize;
- long st_blocks;
- unsigned long __unused[3];
-};
-#endif
-
-
-/* Definitions missing from the standard header files */
-#ifndef O_DIRECTORY
-#if defined(__arm__)
-#define O_DIRECTORY 0040000
-#else
-#define O_DIRECTORY 0200000
-#endif
-#endif
-#ifndef PR_GET_DUMPABLE
-#define PR_GET_DUMPABLE 3
-#endif
-#ifndef PR_SET_DUMPABLE
-#define PR_SET_DUMPABLE 4
-#endif
-#ifndef AT_FDCWD
-#define AT_FDCWD (-100)
-#endif
-#ifndef AT_SYMLINK_NOFOLLOW
-#define AT_SYMLINK_NOFOLLOW 0x100
-#endif
-#ifndef AT_REMOVEDIR
-#define AT_REMOVEDIR 0x200
-#endif
-#ifndef MREMAP_FIXED
-#define MREMAP_FIXED 2
-#endif
-#ifndef SA_RESTORER
-#define SA_RESTORER 0x04000000
-#endif
-
-#if defined(__i386__)
-#ifndef __NR_rt_sigaction
-#define __NR_rt_sigaction 174
-#define __NR_rt_sigprocmask 175
-#endif
-#ifndef __NR_stat64
-#define __NR_stat64 195
-#endif
-#ifndef __NR_fstat64
-#define __NR_fstat64 197
-#endif
-#ifndef __NR_getdents64
-#define __NR_getdents64 220
-#endif
-#ifndef __NR_gettid
-#define __NR_gettid 224
-#endif
-#ifndef __NR_futex
-#define __NR_futex 240
-#endif
-#ifndef __NR_openat
-#define __NR_openat 295
-#endif
-#ifndef __NR_getcpu
-#define __NR_getcpu 318
-#endif
-/* End of i386 definitions */
-#elif defined(__arm__)
-#ifndef __syscall
-#if defined(__thumb__) || defined(__ARM_EABI__)
-#define __SYS_REG(name) register long __sysreg __asm__("r6") = __NR_##name;
-#define __SYS_REG_LIST(regs...) [sysreg] "r" (__sysreg) , ##regs
-#define __syscall(name) "swi\t0"
-#define __syscall_safe(name) \
- "push {r7}\n" \
- "mov r7,%[sysreg]\n" \
- __syscall(name)"\n" \
- "pop {r7}"
-#else
-#define __SYS_REG(name)
-#define __SYS_REG_LIST(regs...) regs
-#define __syscall(name) "swi\t" __sys1(__NR_##name) ""
-#define __syscall_safe(name) __syscall(name)
-#endif
-#endif
-#ifndef __NR_rt_sigaction
-#define __NR_rt_sigaction (__NR_SYSCALL_BASE + 174)
-#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE + 175)
-#endif
-#ifndef __NR_stat64
-#define __NR_stat64 (__NR_SYSCALL_BASE + 195)
-#endif
-#ifndef __NR_fstat64
-#define __NR_fstat64 (__NR_SYSCALL_BASE + 197)
-#endif
-#ifndef __NR_getdents64
-#define __NR_getdents64 (__NR_SYSCALL_BASE + 217)
-#endif
-#ifndef __NR_gettid
-#define __NR_gettid (__NR_SYSCALL_BASE + 224)
-#endif
-#ifndef __NR_futex
-#define __NR_futex (__NR_SYSCALL_BASE + 240)
-#endif
-/* End of ARM definitions */
-#elif defined(__x86_64__)
-#ifndef __NR_gettid
-#define __NR_gettid 186
-#endif
-#ifndef __NR_futex
-#define __NR_futex 202
-#endif
-#ifndef __NR_getdents64
-#define __NR_getdents64 217
-#endif
-#ifndef __NR_openat
-#define __NR_openat 257
-#endif
-/* End of x86-64 definitions */
-#elif defined(__mips__)
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-#ifndef __NR_rt_sigaction
-#define __NR_rt_sigaction (__NR_Linux + 194)
-#define __NR_rt_sigprocmask (__NR_Linux + 195)
-#endif
-#ifndef __NR_stat64
-#define __NR_stat64 (__NR_Linux + 213)
-#endif
-#ifndef __NR_fstat64
-#define __NR_fstat64 (__NR_Linux + 215)
-#endif
-#ifndef __NR_getdents64
-#define __NR_getdents64 (__NR_Linux + 219)
-#endif
-#ifndef __NR_gettid
-#define __NR_gettid (__NR_Linux + 222)
-#endif
-#ifndef __NR_futex
-#define __NR_futex (__NR_Linux + 238)
-#endif
-#ifndef __NR_openat
-#define __NR_openat (__NR_Linux + 288)
-#endif
-#ifndef __NR_fstatat
-#define __NR_fstatat (__NR_Linux + 293)
-#endif
-#ifndef __NR_getcpu
-#define __NR_getcpu (__NR_Linux + 312)
-#endif
-/* End of MIPS (old 32bit API) definitions */
-#elif _MIPS_SIM == _MIPS_SIM_ABI64
-#ifndef __NR_gettid
-#define __NR_gettid (__NR_Linux + 178)
-#endif
-#ifndef __NR_futex
-#define __NR_futex (__NR_Linux + 194)
-#endif
-#ifndef __NR_openat
-#define __NR_openat (__NR_Linux + 247)
-#endif
-#ifndef __NR_fstatat
-#define __NR_fstatat (__NR_Linux + 252)
-#endif
-#ifndef __NR_getcpu
-#define __NR_getcpu (__NR_Linux + 271)
-#endif
-/* End of MIPS (64bit API) definitions */
-#else
-#ifndef __NR_gettid
-#define __NR_gettid (__NR_Linux + 178)
-#endif
-#ifndef __NR_futex
-#define __NR_futex (__NR_Linux + 194)
-#endif
-#ifndef __NR_openat
-#define __NR_openat (__NR_Linux + 251)
-#endif
-#ifndef __NR_fstatat
-#define __NR_fstatat (__NR_Linux + 256)
-#endif
-#ifndef __NR_getcpu
-#define __NR_getcpu (__NR_Linux + 275)
-#endif
-/* End of MIPS (new 32bit API) definitions */
-#endif
-/* End of MIPS definitions */
-#elif defined(__PPC__)
-#ifndef __NR_rt_sigaction
-#define __NR_rt_sigaction 173
-#define __NR_rt_sigprocmask 174
-#endif
-#ifndef __NR_stat64
-#define __NR_stat64 195
-#endif
-#ifndef __NR_fstat64
-#define __NR_fstat64 197
-#endif
-#ifndef __NR_socket
-#define __NR_socket 198
-#endif
-#ifndef __NR_getdents64
-#define __NR_getdents64 202
-#endif
-#ifndef __NR_gettid
-#define __NR_gettid 207
-#endif
-#ifndef __NR_futex
-#define __NR_futex 221
-#endif
-#ifndef __NR_openat
-#define __NR_openat 286
-#endif
-#ifndef __NR_getcpu
-#define __NR_getcpu 302
-#endif
-/* End of powerpc defininitions */
-#elif defined(__aarch64__)
-#ifndef __NR_fstatat
-#define __NR_fstatat 79
-#endif
-/* End of aarch64 defininitions */
-#elif defined(__s390x__)
-#ifndef __NR_quotactl
-#define __NR_quotactl 131
-#endif
-#ifndef __NR_rt_sigreturn
-#define __NR_rt_sigreturn 173
-#endif
-#ifndef __NR_rt_sigaction
-#define __NR_rt_sigaction 174
-#endif
-#ifndef __NR_rt_sigprocmask
-#define __NR_rt_sigprocmask 175
-#endif
-#ifndef __NR_rt_sigpending
-#define __NR_rt_sigpending 176
-#endif
-#ifndef __NR_rt_sigsuspend
-#define __NR_rt_sigsuspend 179
-#endif
-#ifndef __NR_pread64
-#define __NR_pread64 180
-#endif
-#ifndef __NR_pwrite64
-#define __NR_pwrite64 181
-#endif
-#ifndef __NR_getrlimit
-#define __NR_getrlimit 191
-#endif
-#ifndef __NR_setresuid
-#define __NR_setresuid 208
-#endif
-#ifndef __NR_getresuid
-#define __NR_getresuid 209
-#endif
-#ifndef __NR_setresgid
-#define __NR_setresgid 210
-#endif
-#ifndef __NR_getresgid
-#define __NR_getresgid 211
-#endif
-#ifndef __NR_setfsuid
-#define __NR_setfsuid 215
-#endif
-#ifndef __NR_setfsgid
-#define __NR_setfsgid 216
-#endif
-#ifndef __NR_getdents64
-#define __NR_getdents64 220
-#endif
-#ifndef __NR_readahead
-#define __NR_readahead 222
-#endif
-#ifndef __NR_setxattr
-#define __NR_setxattr 224
-#endif
-#ifndef __NR_lsetxattr
-#define __NR_lsetxattr 225
-#endif
-#ifndef __NR_getxattr
-#define __NR_getxattr 227
-#endif
-#ifndef __NR_lgetxattr
-#define __NR_lgetxattr 228
-#endif
-#ifndef __NR_listxattr
-#define __NR_listxattr 230
-#endif
-#ifndef __NR_llistxattr
-#define __NR_llistxattr 231
-#endif
-#ifndef __NR_gettid
-#define __NR_gettid 236
-#endif
-#ifndef __NR_tkill
-#define __NR_tkill 237
-#endif
-#ifndef __NR_futex
-#define __NR_futex 238
-#endif
-#ifndef __NR_sched_setaffinity
-#define __NR_sched_setaffinity 239
-#endif
-#ifndef __NR_sched_getaffinity
-#define __NR_sched_getaffinity 240
-#endif
-#ifndef __NR_set_tid_address
-#define __NR_set_tid_address 252
-#endif
-#ifndef __NR_fadvise64
-#define __NR_fadvise64 253
-#endif
-#ifndef __NR_clock_gettime
-#define __NR_clock_gettime 260
-#endif
-#ifndef __NR_clock_getres
-#define __NR_clock_getres 261
-#endif
-#ifndef __NR_statfs64
-#define __NR_statfs64 265
-#endif
-#ifndef __NR_fstatfs64
-#define __NR_fstatfs64 266
-#endif
-#ifndef __NR_ioprio_set
-#define __NR_ioprio_set 282
-#endif
-#ifndef __NR_ioprio_get
-#define __NR_ioprio_get 283
-#endif
-#ifndef __NR_openat
-#define __NR_openat 288
-#endif
-#ifndef __NR_newfstatat
-#define __NR_newfstatat 293
-#endif
-#ifndef __NR_unlinkat
-#define __NR_unlinkat 294
-#endif
-#ifndef __NR_move_pages
-#define __NR_move_pages 310
-#endif
-#ifndef __NR_getcpu
-#define __NR_getcpu 311
-#endif
-#ifndef __NR_fallocate
-#define __NR_fallocate 314
-#endif
-/* End of s390x definitions */
-#endif
-
-
-/* After forking, we must make sure to only call system calls. */
-#if __BOUNDED_POINTERS__
- #error "Need to port invocations of syscalls for bounded ptrs"
-#else
- /* The core dumper and the thread lister get executed after threads
- * have been suspended. As a consequence, we cannot call any functions
- * that acquire locks. Unfortunately, libc wraps most system calls
- * (e.g. in order to implement pthread_atfork, and to make calls
- * cancellable), which means we cannot call these functions. Instead,
- * we have to call syscall() directly.
- */
- #undef LSS_ERRNO
- #ifdef SYS_ERRNO
- /* Allow the including file to override the location of errno. This can
- * be useful when using clone() with the CLONE_VM option.
- */
- #define LSS_ERRNO SYS_ERRNO
- #else
- #define LSS_ERRNO errno
- #endif
-
- #undef LSS_INLINE
- #ifdef SYS_INLINE
- #define LSS_INLINE SYS_INLINE
- #else
- #define LSS_INLINE static inline
- #endif
-
- /* Allow the including file to override the prefix used for all new
- * system calls. By default, it will be set to "sys_".
- */
- #undef LSS_NAME
- #ifndef SYS_PREFIX
- #define LSS_NAME(name) sys_##name
- #elif SYS_PREFIX < 0
- #define LSS_NAME(name) name
- #elif SYS_PREFIX == 0
- #define LSS_NAME(name) sys0_##name
- #elif SYS_PREFIX == 1
- #define LSS_NAME(name) sys1_##name
- #elif SYS_PREFIX == 2
- #define LSS_NAME(name) sys2_##name
- #elif SYS_PREFIX == 3
- #define LSS_NAME(name) sys3_##name
- #elif SYS_PREFIX == 4
- #define LSS_NAME(name) sys4_##name
- #elif SYS_PREFIX == 5
- #define LSS_NAME(name) sys5_##name
- #elif SYS_PREFIX == 6
- #define LSS_NAME(name) sys6_##name
- #elif SYS_PREFIX == 7
- #define LSS_NAME(name) sys7_##name
- #elif SYS_PREFIX == 8
- #define LSS_NAME(name) sys8_##name
- #elif SYS_PREFIX == 9
- #define LSS_NAME(name) sys9_##name
- #endif
-
- #undef LSS_RETURN
- #if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
- defined(__aarch64__) || defined(__s390x__))
- /* Failing system calls return a negative result in the range of
- * -1..-4095. These are "errno" values with the sign inverted.
- */
- #define LSS_RETURN(type, res) \
- do { \
- if ((unsigned long)(res) >= (unsigned long)(-4095)) { \
- LSS_ERRNO = -(res); \
- res = -1; \
- } \
- return (type) (res); \
- } while (0)
- #elif defined(__mips__)
- /* On MIPS, failing system calls return -1, and set errno in a
- * separate CPU register.
- */
- #define LSS_RETURN(type, res, err) \
- do { \
- if (err) { \
- LSS_ERRNO = (res); \
- res = -1; \
- } \
- return (type) (res); \
- } while (0)
- #elif defined(__PPC__)
- /* On PPC, failing system calls return -1, and set errno in a
- * separate CPU register. See linux/unistd.h.
- */
- #define LSS_RETURN(type, res, err) \
- do { \
- if (err & 0x10000000 ) { \
- LSS_ERRNO = (res); \
- res = -1; \
- } \
- return (type) (res); \
- } while (0)
- #endif
- #if defined(__i386__)
- #if defined(NO_FRAME_POINTER) && (100 * __GNUC__ + __GNUC_MINOR__ >= 404)
- /* This only works for GCC-4.4 and above -- the first version to use
- .cfi directives for dwarf unwind info. */
- #define CFI_ADJUST_CFA_OFFSET(adjust) \
- ".cfi_adjust_cfa_offset " #adjust "\n"
- #else
- #define CFI_ADJUST_CFA_OFFSET(adjust) /**/
- #endif
-
- /* In PIC mode (e.g. when building shared libraries), gcc for i386
- * reserves ebx. Unfortunately, most distribution ship with implementations
- * of _syscallX() which clobber ebx.
- * Also, most definitions of _syscallX() neglect to mark "memory" as being
- * clobbered. This causes problems with compilers, that do a better job
- * at optimizing across __asm__ calls.
- * So, we just have to redefine all of the _syscallX() macros.
- */
- #undef LSS_BODY
- #define LSS_BODY(type,args...) \
- long __res; \
- __asm__ __volatile__("push %%ebx\n" \
- CFI_ADJUST_CFA_OFFSET(4) \
- "movl %2,%%ebx\n" \
- "int $0x80\n" \
- "pop %%ebx\n" \
- CFI_ADJUST_CFA_OFFSET(-4) \
- args \
- : "esp", "memory"); \
- LSS_RETURN(type,__res)
- #undef _syscall0
- #define _syscall0(type,name) \
- type LSS_NAME(name)(void) { \
- long __res; \
- __asm__ volatile("int $0x80" \
- : "=a" (__res) \
- : "0" (__NR_##name) \
- : "memory"); \
- LSS_RETURN(type,__res); \
- }
- #undef _syscall1
- #define _syscall1(type,name,type1,arg1) \
- type LSS_NAME(name)(type1 arg1) { \
- LSS_BODY(type, \
- : "=a" (__res) \
- : "0" (__NR_##name), "ri" ((long)(arg1))); \
- }
- #undef _syscall2
- #define _syscall2(type,name,type1,arg1,type2,arg2) \
- type LSS_NAME(name)(type1 arg1,type2 arg2) { \
- LSS_BODY(type, \
- : "=a" (__res) \
- : "0" (__NR_##name),"ri" ((long)(arg1)), "c" ((long)(arg2))); \
- }
- #undef _syscall3
- #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
- type LSS_NAME(name)(type1 arg1,type2 arg2,type3 arg3) { \
- LSS_BODY(type, \
- : "=a" (__res) \
- : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \
- "d" ((long)(arg3))); \
- }
- #undef _syscall4
- #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- LSS_BODY(type, \
- : "=a" (__res) \
- : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \
- "d" ((long)(arg3)),"S" ((long)(arg4))); \
- }
- #undef _syscall5
- #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5) { \
- long __res; \
- __asm__ __volatile__("push %%ebx\n" \
- "movl %2,%%ebx\n" \
- "movl %1,%%eax\n" \
- "int $0x80\n" \
- "pop %%ebx" \
- : "=a" (__res) \
- : "i" (__NR_##name), "ri" ((long)(arg1)), \
- "c" ((long)(arg2)), "d" ((long)(arg3)), \
- "S" ((long)(arg4)), "D" ((long)(arg5)) \
- : "esp", "memory"); \
- LSS_RETURN(type,__res); \
- }
- #undef _syscall6
- #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5,type6,arg6) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5, type6 arg6) { \
- long __res; \
- struct { long __a1; long __a6; } __s = { (long)arg1, (long) arg6 }; \
- __asm__ __volatile__("push %%ebp\n" \
- "push %%ebx\n" \
- "movl 4(%2),%%ebp\n" \
- "movl 0(%2), %%ebx\n" \
- "movl %1,%%eax\n" \
- "int $0x80\n" \
- "pop %%ebx\n" \
- "pop %%ebp" \
- : "=a" (__res) \
- : "i" (__NR_##name), "0" ((long)(&__s)), \
- "c" ((long)(arg2)), "d" ((long)(arg3)), \
- "S" ((long)(arg4)), "D" ((long)(arg5)) \
- : "esp", "memory"); \
- LSS_RETURN(type,__res); \
- }
- LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
- int flags, void *arg, int *parent_tidptr,
- void *newtls, int *child_tidptr) {
- long __res;
- __asm__ __volatile__(/* if (fn == NULL)
- * return -EINVAL;
- */
- "movl %3,%%ecx\n"
- "jecxz 1f\n"
-
- /* if (child_stack == NULL)
- * return -EINVAL;
- */
- "movl %4,%%ecx\n"
- "jecxz 1f\n"
-
- /* Set up alignment of the child stack:
- * child_stack = (child_stack & ~0xF) - 20;
- */
- "andl $-16,%%ecx\n"
- "subl $20,%%ecx\n"
-
- /* Push "arg" and "fn" onto the stack that will be
- * used by the child.
- */
- "movl %6,%%eax\n"
- "movl %%eax,4(%%ecx)\n"
- "movl %3,%%eax\n"
- "movl %%eax,(%%ecx)\n"
-
- /* %eax = syscall(%eax = __NR_clone,
- * %ebx = flags,
- * %ecx = child_stack,
- * %edx = parent_tidptr,
- * %esi = newtls,
- * %edi = child_tidptr)
- * Also, make sure that %ebx gets preserved as it is
- * used in PIC mode.
- */
- "movl %8,%%esi\n"
- "movl %7,%%edx\n"
- "movl %5,%%eax\n"
- "movl %9,%%edi\n"
- "pushl %%ebx\n"
- "movl %%eax,%%ebx\n"
- "movl %2,%%eax\n"
- "int $0x80\n"
-
- /* In the parent: restore %ebx
- * In the child: move "fn" into %ebx
- */
- "popl %%ebx\n"
-
- /* if (%eax != 0)
- * return %eax;
- */
- "test %%eax,%%eax\n"
- "jnz 1f\n"
-
- /* In the child, now. Terminate frame pointer chain.
- */
- "movl $0,%%ebp\n"
-
- /* Call "fn". "arg" is already on the stack.
- */
- "call *%%ebx\n"
-
- /* Call _exit(%ebx). Unfortunately older versions
- * of gcc restrict the number of arguments that can
- * be passed to asm(). So, we need to hard-code the
- * system call number.
- */
- "movl %%eax,%%ebx\n"
- "movl $1,%%eax\n"
- "int $0x80\n"
-
- /* Return to parent.
- */
- "1:\n"
- : "=a" (__res)
- : "0"(-EINVAL), "i"(__NR_clone),
- "m"(fn), "m"(child_stack), "m"(flags), "m"(arg),
- "m"(parent_tidptr), "m"(newtls), "m"(child_tidptr)
- : "esp", "memory", "ecx", "edx", "esi", "edi");
- LSS_RETURN(int, __res);
- }
-
- LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) {
- /* On i386, the kernel does not know how to return from a signal
- * handler. Instead, it relies on user space to provide a
- * restorer function that calls the {rt_,}sigreturn() system call.
- * Unfortunately, we cannot just reference the glibc version of this
- * function, as glibc goes out of its way to make it inaccessible.
- */
- void (*res)(void);
- __asm__ __volatile__("call 2f\n"
- "0:.align 16\n"
- "1:movl %1,%%eax\n"
- "int $0x80\n"
- "2:popl %0\n"
- "addl $(1b-0b),%0\n"
- : "=a" (res)
- : "i" (__NR_rt_sigreturn));
- return res;
- }
- LSS_INLINE void (*LSS_NAME(restore)(void))(void) {
- /* On i386, the kernel does not know how to return from a signal
- * handler. Instead, it relies on user space to provide a
- * restorer function that calls the {rt_,}sigreturn() system call.
- * Unfortunately, we cannot just reference the glibc version of this
- * function, as glibc goes out of its way to make it inaccessible.
- */
- void (*res)(void);
- __asm__ __volatile__("call 2f\n"
- "0:.align 16\n"
- "1:pop %%eax\n"
- "movl %1,%%eax\n"
- "int $0x80\n"
- "2:popl %0\n"
- "addl $(1b-0b),%0\n"
- : "=a" (res)
- : "i" (__NR_sigreturn));
- return res;
- }
- #elif defined(__x86_64__)
- /* There are no known problems with any of the _syscallX() macros
- * currently shipping for x86_64, but we still need to be able to define
- * our own version so that we can override the location of the errno
- * location (e.g. when using the clone() system call with the CLONE_VM
- * option).
- */
- #undef LSS_ENTRYPOINT
- #define LSS_ENTRYPOINT "syscall\n"
-
- /* The x32 ABI has 32 bit longs, but the syscall interface is 64 bit.
- * We need to explicitly cast to an unsigned 64 bit type to avoid implicit
- * sign extension. We can't cast pointers directly because those are
- * 32 bits, and gcc will dump ugly warnings about casting from a pointer
- * to an integer of a different size.
- */
- #undef LSS_SYSCALL_ARG
- #define LSS_SYSCALL_ARG(a) ((uint64_t)(uintptr_t)(a))
- #undef _LSS_RETURN
- #define _LSS_RETURN(type, res, cast) \
- do { \
- if ((uint64_t)(res) >= (uint64_t)(-4095)) { \
- LSS_ERRNO = -(res); \
- res = -1; \
- } \
- return (type)(cast)(res); \
- } while (0)
- #undef LSS_RETURN
- #define LSS_RETURN(type, res) _LSS_RETURN(type, res, uintptr_t)
-
- #undef _LSS_BODY
- #define _LSS_BODY(nr, type, name, cast, ...) \
- long long __res; \
- __asm__ __volatile__(LSS_BODY_ASM##nr LSS_ENTRYPOINT \
- : "=a" (__res) \
- : "0" (__NR_##name) LSS_BODY_ARG##nr(__VA_ARGS__) \
- : LSS_BODY_CLOBBER##nr "r11", "rcx", "memory"); \
- _LSS_RETURN(type, __res, cast)
- #undef LSS_BODY
- #define LSS_BODY(nr, type, name, args...) \
- _LSS_BODY(nr, type, name, uintptr_t, ## args)
-
- #undef LSS_BODY_ASM0
- #undef LSS_BODY_ASM1
- #undef LSS_BODY_ASM2
- #undef LSS_BODY_ASM3
- #undef LSS_BODY_ASM4
- #undef LSS_BODY_ASM5
- #undef LSS_BODY_ASM6
- #define LSS_BODY_ASM0
- #define LSS_BODY_ASM1 LSS_BODY_ASM0
- #define LSS_BODY_ASM2 LSS_BODY_ASM1
- #define LSS_BODY_ASM3 LSS_BODY_ASM2
- #define LSS_BODY_ASM4 LSS_BODY_ASM3 "movq %5,%%r10;"
- #define LSS_BODY_ASM5 LSS_BODY_ASM4 "movq %6,%%r8;"
- #define LSS_BODY_ASM6 LSS_BODY_ASM5 "movq %7,%%r9;"
-
- #undef LSS_BODY_CLOBBER0
- #undef LSS_BODY_CLOBBER1
- #undef LSS_BODY_CLOBBER2
- #undef LSS_BODY_CLOBBER3
- #undef LSS_BODY_CLOBBER4
- #undef LSS_BODY_CLOBBER5
- #undef LSS_BODY_CLOBBER6
- #define LSS_BODY_CLOBBER0
- #define LSS_BODY_CLOBBER1 LSS_BODY_CLOBBER0
- #define LSS_BODY_CLOBBER2 LSS_BODY_CLOBBER1
- #define LSS_BODY_CLOBBER3 LSS_BODY_CLOBBER2
- #define LSS_BODY_CLOBBER4 LSS_BODY_CLOBBER3 "r10",
- #define LSS_BODY_CLOBBER5 LSS_BODY_CLOBBER4 "r8",
- #define LSS_BODY_CLOBBER6 LSS_BODY_CLOBBER5 "r9",
-
- #undef LSS_BODY_ARG0
- #undef LSS_BODY_ARG1
- #undef LSS_BODY_ARG2
- #undef LSS_BODY_ARG3
- #undef LSS_BODY_ARG4
- #undef LSS_BODY_ARG5
- #undef LSS_BODY_ARG6
- #define LSS_BODY_ARG0()
- #define LSS_BODY_ARG1(arg1) \
- LSS_BODY_ARG0(), "D" (arg1)
- #define LSS_BODY_ARG2(arg1, arg2) \
- LSS_BODY_ARG1(arg1), "S" (arg2)
- #define LSS_BODY_ARG3(arg1, arg2, arg3) \
- LSS_BODY_ARG2(arg1, arg2), "d" (arg3)
- #define LSS_BODY_ARG4(arg1, arg2, arg3, arg4) \
- LSS_BODY_ARG3(arg1, arg2, arg3), "r" (arg4)
- #define LSS_BODY_ARG5(arg1, arg2, arg3, arg4, arg5) \
- LSS_BODY_ARG4(arg1, arg2, arg3, arg4), "r" (arg5)
- #define LSS_BODY_ARG6(arg1, arg2, arg3, arg4, arg5, arg6) \
- LSS_BODY_ARG5(arg1, arg2, arg3, arg4, arg5), "r" (arg6)
-
- #undef _syscall0
- #define _syscall0(type,name) \
- type LSS_NAME(name)() { \
- LSS_BODY(0, type, name); \
- }
- #undef _syscall1
- #define _syscall1(type,name,type1,arg1) \
- type LSS_NAME(name)(type1 arg1) { \
- LSS_BODY(1, type, name, LSS_SYSCALL_ARG(arg1)); \
- }
- #undef _syscall2
- #define _syscall2(type,name,type1,arg1,type2,arg2) \
- type LSS_NAME(name)(type1 arg1, type2 arg2) { \
- LSS_BODY(2, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2));\
- }
- #undef _syscall3
- #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
- LSS_BODY(3, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \
- LSS_SYSCALL_ARG(arg3)); \
- }
- #undef _syscall4
- #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- LSS_BODY(4, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \
- LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4));\
- }
- #undef _syscall5
- #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5) { \
- LSS_BODY(5, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \
- LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4), \
- LSS_SYSCALL_ARG(arg5)); \
- }
- #undef _syscall6
- #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5,type6,arg6) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5, type6 arg6) { \
- LSS_BODY(6, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \
- LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4), \
- LSS_SYSCALL_ARG(arg5), LSS_SYSCALL_ARG(arg6));\
- }
- LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
- int flags, void *arg, int *parent_tidptr,
- void *newtls, int *child_tidptr) {
- long long __res;
- {
- __asm__ __volatile__(/* if (fn == NULL)
- * return -EINVAL;
- */
- "testq %4,%4\n"
- "jz 1f\n"
-
- /* if (child_stack == NULL)
- * return -EINVAL;
- */
- "testq %5,%5\n"
- "jz 1f\n"
-
- /* Set up alignment of the child stack:
- * child_stack = (child_stack & ~0xF) - 16;
- */
- "andq $-16,%5\n"
- "subq $16,%5\n"
-
- /* Push "arg" and "fn" onto the stack that will be
- * used by the child.
- */
- "movq %7,8(%5)\n"
- "movq %4,0(%5)\n"
-
- /* %rax = syscall(%rax = __NR_clone,
- * %rdi = flags,
- * %rsi = child_stack,
- * %rdx = parent_tidptr,
- * %r8 = new_tls,
- * %r10 = child_tidptr)
- */
- "movq %2,%%rax\n"
- "movq %9,%%r8\n"
- "movq %10,%%r10\n"
- "syscall\n"
-
- /* if (%rax != 0)
- * return;
- */
- "testq %%rax,%%rax\n"
- "jnz 1f\n"
-
- /* In the child. Terminate frame pointer chain.
- */
- "xorq %%rbp,%%rbp\n"
-
- /* Call "fn(arg)".
- */
- "popq %%rax\n"
- "popq %%rdi\n"
- "call *%%rax\n"
-
- /* Call _exit(%ebx).
- */
- "movq %%rax,%%rdi\n"
- "movq %3,%%rax\n"
- "syscall\n"
-
- /* Return to parent.
- */
- "1:\n"
- : "=a" (__res)
- : "0"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit),
- "r"(LSS_SYSCALL_ARG(fn)),
- "S"(LSS_SYSCALL_ARG(child_stack)),
- "D"(LSS_SYSCALL_ARG(flags)),
- "r"(LSS_SYSCALL_ARG(arg)),
- "d"(LSS_SYSCALL_ARG(parent_tidptr)),
- "r"(LSS_SYSCALL_ARG(newtls)),
- "r"(LSS_SYSCALL_ARG(child_tidptr))
- : "rsp", "memory", "r8", "r10", "r11", "rcx");
- }
- LSS_RETURN(int, __res);
- }
-
- LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) {
- /* On x86-64, the kernel does not know how to return from
- * a signal handler. Instead, it relies on user space to provide a
- * restorer function that calls the rt_sigreturn() system call.
- * Unfortunately, we cannot just reference the glibc version of this
- * function, as glibc goes out of its way to make it inaccessible.
- */
- long long res;
- __asm__ __volatile__("call 2f\n"
- "0:.align 16\n"
- "1:movq %1,%%rax\n"
- "syscall\n"
- "2:popq %0\n"
- "addq $(1b-0b),%0\n"
- : "=a" (res)
- : "i" (__NR_rt_sigreturn));
- return (void (*)(void))(uintptr_t)res;
- }
- #elif defined(__arm__)
- /* Most definitions of _syscallX() neglect to mark "memory" as being
- * clobbered. This causes problems with compilers, that do a better job
- * at optimizing across __asm__ calls.
- * So, we just have to redefine all fo the _syscallX() macros.
- */
- #undef LSS_REG
- #define LSS_REG(r,a) register long __r##r __asm__("r"#r) = (long)a
-
- /* r0..r3 are scratch registers and not preserved across function
- * calls. We need to first evaluate the first 4 syscall arguments
- * and store them on stack. They must be loaded into r0..r3 after
- * all function calls to avoid r0..r3 being clobbered.
- */
- #undef LSS_SAVE_ARG
- #define LSS_SAVE_ARG(r,a) long __tmp##r = (long)a
- #undef LSS_LOAD_ARG
- #define LSS_LOAD_ARG(r) register long __r##r __asm__("r"#r) = __tmp##r
-
- #undef LSS_BODY
- #define LSS_BODY(type, name, args...) \
- register long __res_r0 __asm__("r0"); \
- long __res; \
- __SYS_REG(name) \
- __asm__ __volatile__ (__syscall_safe(name) \
- : "=r"(__res_r0) \
- : __SYS_REG_LIST(args) \
- : "lr", "memory"); \
- __res = __res_r0; \
- LSS_RETURN(type, __res)
- #undef _syscall0
- #define _syscall0(type, name) \
- type LSS_NAME(name)() { \
- LSS_BODY(type, name); \
- }
- #undef _syscall1
- #define _syscall1(type, name, type1, arg1) \
- type LSS_NAME(name)(type1 arg1) { \
- /* There is no need for using a volatile temp. */ \
- LSS_REG(0, arg1); \
- LSS_BODY(type, name, "r"(__r0)); \
- }
- #undef _syscall2
- #define _syscall2(type, name, type1, arg1, type2, arg2) \
- type LSS_NAME(name)(type1 arg1, type2 arg2) { \
- LSS_SAVE_ARG(0, arg1); \
- LSS_SAVE_ARG(1, arg2); \
- LSS_LOAD_ARG(0); \
- LSS_LOAD_ARG(1); \
- LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \
- }
- #undef _syscall3
- #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
- LSS_SAVE_ARG(0, arg1); \
- LSS_SAVE_ARG(1, arg2); \
- LSS_SAVE_ARG(2, arg3); \
- LSS_LOAD_ARG(0); \
- LSS_LOAD_ARG(1); \
- LSS_LOAD_ARG(2); \
- LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \
- }
- #undef _syscall4
- #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
- type4, arg4) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- LSS_SAVE_ARG(0, arg1); \
- LSS_SAVE_ARG(1, arg2); \
- LSS_SAVE_ARG(2, arg3); \
- LSS_SAVE_ARG(3, arg4); \
- LSS_LOAD_ARG(0); \
- LSS_LOAD_ARG(1); \
- LSS_LOAD_ARG(2); \
- LSS_LOAD_ARG(3); \
- LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \
- }
- #undef _syscall5
- #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
- type4, arg4, type5, arg5) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5) { \
- LSS_SAVE_ARG(0, arg1); \
- LSS_SAVE_ARG(1, arg2); \
- LSS_SAVE_ARG(2, arg3); \
- LSS_SAVE_ARG(3, arg4); \
- LSS_REG(4, arg5); \
- LSS_LOAD_ARG(0); \
- LSS_LOAD_ARG(1); \
- LSS_LOAD_ARG(2); \
- LSS_LOAD_ARG(3); \
- LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
- "r"(__r4)); \
- }
- #undef _syscall6
- #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
- type4, arg4, type5, arg5, type6, arg6) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5, type6 arg6) { \
- LSS_SAVE_ARG(0, arg1); \
- LSS_SAVE_ARG(1, arg2); \
- LSS_SAVE_ARG(2, arg3); \
- LSS_SAVE_ARG(3, arg4); \
- LSS_REG(4, arg5); \
- LSS_REG(5, arg6); \
- LSS_LOAD_ARG(0); \
- LSS_LOAD_ARG(1); \
- LSS_LOAD_ARG(2); \
- LSS_LOAD_ARG(3); \
- LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
- "r"(__r4), "r"(__r5)); \
- }
- LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
- int flags, void *arg, int *parent_tidptr,
- void *newtls, int *child_tidptr) {
- register long __res __asm__("r5");
- {
- if (fn == NULL || child_stack == NULL) {
- __res = -EINVAL;
- goto clone_exit;
- }
-
- /* stash first 4 arguments on stack first because we can only load
- * them after all function calls.
- */
- int tmp_flags = flags;
- int * tmp_stack = (int*) child_stack;
- void * tmp_ptid = parent_tidptr;
- void * tmp_tls = newtls;
-
- register int *__ctid __asm__("r4") = child_tidptr;
-
- /* Push "arg" and "fn" onto the stack that will be
- * used by the child.
- */
- *(--tmp_stack) = (int) arg;
- *(--tmp_stack) = (int) fn;
-
- /* We must load r0..r3 last after all possible function calls. */
- register int __flags __asm__("r0") = tmp_flags;
- register void *__stack __asm__("r1") = tmp_stack;
- register void *__ptid __asm__("r2") = tmp_ptid;
- register void *__tls __asm__("r3") = tmp_tls;
-
- /* %r0 = syscall(%r0 = flags,
- * %r1 = child_stack,
- * %r2 = parent_tidptr,
- * %r3 = newtls,
- * %r4 = child_tidptr)
- */
- __SYS_REG(clone)
- __asm__ __volatile__(/* %r0 = syscall(%r0 = flags,
- * %r1 = child_stack,
- * %r2 = parent_tidptr,
- * %r3 = newtls,
- * %r4 = child_tidptr)
- */
- "push {r7}\n"
- "mov r7,%1\n"
- __syscall(clone)"\n"
-
- /* if (%r0 != 0)
- * return %r0;
- */
- "movs %0,r0\n"
- "bne 1f\n"
-
- /* In the child, now. Call "fn(arg)".
- */
- "ldr r0,[sp, #4]\n"
- "mov lr,pc\n"
- "ldr pc,[sp]\n"
-
- /* Call _exit(%r0), which never returns. We only
- * need to set r7 for EABI syscall ABI but we do
- * this always to simplify code sharing between
- * old and new syscall ABIs.
- */
- "mov r7,%2\n"
- __syscall(exit)"\n"
-
- /* Pop r7 from the stack only in the parent.
- */
- "1: pop {r7}\n"
- : "=r" (__res)
- : "r"(__sysreg),
- "i"(__NR_exit), "r"(__stack), "r"(__flags),
- "r"(__ptid), "r"(__tls), "r"(__ctid)
- : "cc", "lr", "memory");
- }
- clone_exit:
- LSS_RETURN(int, __res);
- }
- #elif defined(__mips__)
- #undef LSS_REG
- #define LSS_REG(r,a) register unsigned long __r##r __asm__("$"#r) = \
- (unsigned long)(a)
-
- #if _MIPS_SIM == _MIPS_SIM_ABI32
- // See http://sources.redhat.com/ml/libc-alpha/2004-10/msg00050.html
- // or http://www.linux-mips.org/archives/linux-mips/2004-10/msg00142.html
- #define MIPS_SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12",\
- "$13", "$14", "$15", "$24", "$25", "memory"
- #else
- #define MIPS_SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
- "$14", "$15", "$24", "$25", "memory"
- #endif
-
- #undef LSS_BODY
- #define LSS_BODY(type,name,r7,...) \
- register unsigned long __v0 __asm__("$2") = __NR_##name; \
- __asm__ __volatile__ ("syscall\n" \
- : "=&r"(__v0), r7 (__r7) \
- : "0"(__v0), ##__VA_ARGS__ \
- : MIPS_SYSCALL_CLOBBERS); \
- LSS_RETURN(type, __v0, __r7)
- #undef _syscall0
- #define _syscall0(type, name) \
- type LSS_NAME(name)() { \
- register unsigned long __r7 __asm__("$7"); \
- LSS_BODY(type, name, "=r"); \
- }
- #undef _syscall1
- #define _syscall1(type, name, type1, arg1) \
- type LSS_NAME(name)(type1 arg1) { \
- register unsigned long __r7 __asm__("$7"); \
- LSS_REG(4, arg1); LSS_BODY(type, name, "=r", "r"(__r4)); \
- }
- #undef _syscall2
- #define _syscall2(type, name, type1, arg1, type2, arg2) \
- type LSS_NAME(name)(type1 arg1, type2 arg2) { \
- register unsigned long __r7 __asm__("$7"); \
- LSS_REG(4, arg1); LSS_REG(5, arg2); \
- LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5)); \
- }
- #undef _syscall3
- #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
- register unsigned long __r7 __asm__("$7"); \
- LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
- LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5), "r"(__r6)); \
- }
- #undef _syscall4
- #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
- LSS_REG(7, arg4); \
- LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6)); \
- }
- #undef _syscall5
- #if _MIPS_SIM == _MIPS_SIM_ABI32
- /* The old 32bit MIPS system call API passes the fifth and sixth argument
- * on the stack, whereas the new APIs use registers "r8" and "r9".
- */
- #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5) { \
- LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
- LSS_REG(7, arg4); \
- register unsigned long __v0 __asm__("$2"); \
- __asm__ __volatile__ (".set noreorder\n" \
- "lw $2, %6\n" \
- "subu $29, 32\n" \
- "sw $2, 16($29)\n" \
- "li $2, %2\n" \
- "syscall\n" \
- "addiu $29, 32\n" \
- ".set reorder\n" \
- : "=&r"(__v0), "+r" (__r7) \
- : "i" (__NR_##name), "r"(__r4), "r"(__r5), \
- "r"(__r6), "m" ((unsigned long)arg5) \
- : MIPS_SYSCALL_CLOBBERS); \
- LSS_RETURN(type, __v0, __r7); \
- }
- #else
- #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5) { \
- LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
- LSS_REG(7, arg4); LSS_REG(8, arg5); \
- LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \
- "r"(__r8)); \
- }
- #endif
- #undef _syscall6
- #if _MIPS_SIM == _MIPS_SIM_ABI32
- /* The old 32bit MIPS system call API passes the fifth and sixth argument
- * on the stack, whereas the new APIs use registers "r8" and "r9".
- */
- #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5,type6,arg6) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5, type6 arg6) { \
- LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
- LSS_REG(7, arg4); \
- register unsigned long __v0 __asm__("$2"); \
- __asm__ __volatile__ (".set noreorder\n" \
- "lw $2, %6\n" \
- "lw $8, %7\n" \
- "subu $29, 32\n" \
- "sw $2, 16($29)\n" \
- "sw $8, 20($29)\n" \
- "li $2, %2\n" \
- "syscall\n" \
- "addiu $29, 32\n" \
- ".set reorder\n" \
- : "=&r"(__v0), "+r" (__r7) \
- : "i" (__NR_##name), "r"(__r4), "r"(__r5), \
- "r"(__r6), "m" ((unsigned long)arg5), \
- "m" ((unsigned long)arg6) \
- : MIPS_SYSCALL_CLOBBERS); \
- LSS_RETURN(type, __v0, __r7); \
- }
- #else
- #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5,type6,arg6) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5,type6 arg6) { \
- LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
- LSS_REG(7, arg4); LSS_REG(8, arg5); LSS_REG(9, arg6); \
- LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \
- "r"(__r8), "r"(__r9)); \
- }
- #endif
- LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
- int flags, void *arg, int *parent_tidptr,
- void *newtls, int *child_tidptr) {
- register unsigned long __v0 __asm__("$2");
- register unsigned long __r7 __asm__("$7") = (unsigned long)newtls;
- {
- register int __flags __asm__("$4") = flags;
- register void *__stack __asm__("$5") = child_stack;
- register void *__ptid __asm__("$6") = parent_tidptr;
- register int *__ctid __asm__("$8") = child_tidptr;
- __asm__ __volatile__(
- #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32
- "subu $29,24\n"
- #elif _MIPS_SIM == _MIPS_SIM_NABI32
- "sub $29,16\n"
- #else
- "dsubu $29,16\n"
- #endif
-
- /* if (fn == NULL || child_stack == NULL)
- * return -EINVAL;
- */
- "li %0,%2\n"
- "beqz %5,1f\n"
- "beqz %6,1f\n"
-
- /* Push "arg" and "fn" onto the stack that will be
- * used by the child.
- */
- #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32
- "subu %6,32\n"
- "sw %5,0(%6)\n"
- "sw %8,4(%6)\n"
- #elif _MIPS_SIM == _MIPS_SIM_NABI32
- "sub %6,32\n"
- "sw %5,0(%6)\n"
- "sw %8,8(%6)\n"
- #else
- "dsubu %6,32\n"
- "sd %5,0(%6)\n"
- "sd %8,8(%6)\n"
- #endif
-
- /* $7 = syscall($4 = flags,
- * $5 = child_stack,
- * $6 = parent_tidptr,
- * $7 = newtls,
- * $8 = child_tidptr)
- */
- "li $2,%3\n"
- "syscall\n"
-
- /* if ($7 != 0)
- * return $2;
- */
- "bnez $7,1f\n"
- "bnez $2,1f\n"
-
- /* In the child, now. Call "fn(arg)".
- */
- #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32
- "lw $25,0($29)\n"
- "lw $4,4($29)\n"
- #elif _MIPS_SIM == _MIPS_SIM_NABI32
- "lw $25,0($29)\n"
- "lw $4,8($29)\n"
- #else
- "ld $25,0($29)\n"
- "ld $4,8($29)\n"
- #endif
- "jalr $25\n"
-
- /* Call _exit($2)
- */
- "move $4,$2\n"
- "li $2,%4\n"
- "syscall\n"
-
- "1:\n"
- #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32
- "addu $29, 24\n"
- #elif _MIPS_SIM == _MIPS_SIM_NABI32
- "add $29, 16\n"
- #else
- "daddu $29,16\n"
- #endif
- : "=&r" (__v0), "=r" (__r7)
- : "i"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit),
- "r"(fn), "r"(__stack), "r"(__flags), "r"(arg),
- "r"(__ptid), "r"(__r7), "r"(__ctid)
- : "$9", "$10", "$11", "$12", "$13", "$14", "$15",
- "$24", "memory");
- }
- LSS_RETURN(int, __v0, __r7);
- }
- #elif defined (__PPC__)
- #undef LSS_LOADARGS_0
- #define LSS_LOADARGS_0(name, dummy...) \
- __sc_0 = __NR_##name
- #undef LSS_LOADARGS_1
- #define LSS_LOADARGS_1(name, arg1) \
- LSS_LOADARGS_0(name); \
- __sc_3 = (unsigned long) (arg1)
- #undef LSS_LOADARGS_2
- #define LSS_LOADARGS_2(name, arg1, arg2) \
- LSS_LOADARGS_1(name, arg1); \
- __sc_4 = (unsigned long) (arg2)
- #undef LSS_LOADARGS_3
- #define LSS_LOADARGS_3(name, arg1, arg2, arg3) \
- LSS_LOADARGS_2(name, arg1, arg2); \
- __sc_5 = (unsigned long) (arg3)
- #undef LSS_LOADARGS_4
- #define LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4) \
- LSS_LOADARGS_3(name, arg1, arg2, arg3); \
- __sc_6 = (unsigned long) (arg4)
- #undef LSS_LOADARGS_5
- #define LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \
- LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4); \
- __sc_7 = (unsigned long) (arg5)
- #undef LSS_LOADARGS_6
- #define LSS_LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
- LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \
- __sc_8 = (unsigned long) (arg6)
- #undef LSS_ASMINPUT_0
- #define LSS_ASMINPUT_0 "0" (__sc_0)
- #undef LSS_ASMINPUT_1
- #define LSS_ASMINPUT_1 LSS_ASMINPUT_0, "1" (__sc_3)
- #undef LSS_ASMINPUT_2
- #define LSS_ASMINPUT_2 LSS_ASMINPUT_1, "2" (__sc_4)
- #undef LSS_ASMINPUT_3
- #define LSS_ASMINPUT_3 LSS_ASMINPUT_2, "3" (__sc_5)
- #undef LSS_ASMINPUT_4
- #define LSS_ASMINPUT_4 LSS_ASMINPUT_3, "4" (__sc_6)
- #undef LSS_ASMINPUT_5
- #define LSS_ASMINPUT_5 LSS_ASMINPUT_4, "5" (__sc_7)
- #undef LSS_ASMINPUT_6
- #define LSS_ASMINPUT_6 LSS_ASMINPUT_5, "6" (__sc_8)
- #undef LSS_BODY
- #define LSS_BODY(nr, type, name, args...) \
- long __sc_ret, __sc_err; \
- { \
- register unsigned long __sc_0 __asm__ ("r0"); \
- register unsigned long __sc_3 __asm__ ("r3"); \
- register unsigned long __sc_4 __asm__ ("r4"); \
- register unsigned long __sc_5 __asm__ ("r5"); \
- register unsigned long __sc_6 __asm__ ("r6"); \
- register unsigned long __sc_7 __asm__ ("r7"); \
- register unsigned long __sc_8 __asm__ ("r8"); \
- \
- LSS_LOADARGS_##nr(name, args); \
- __asm__ __volatile__ \
- ("sc\n\t" \
- "mfcr %0" \
- : "=&r" (__sc_0), \
- "=&r" (__sc_3), "=&r" (__sc_4), \
- "=&r" (__sc_5), "=&r" (__sc_6), \
- "=&r" (__sc_7), "=&r" (__sc_8) \
- : LSS_ASMINPUT_##nr \
- : "cr0", "ctr", "memory", \
- "r9", "r10", "r11", "r12"); \
- __sc_ret = __sc_3; \
- __sc_err = __sc_0; \
- } \
- LSS_RETURN(type, __sc_ret, __sc_err)
- #undef _syscall0
- #define _syscall0(type, name) \
- type LSS_NAME(name)(void) { \
- LSS_BODY(0, type, name); \
- }
- #undef _syscall1
- #define _syscall1(type, name, type1, arg1) \
- type LSS_NAME(name)(type1 arg1) { \
- LSS_BODY(1, type, name, arg1); \
- }
- #undef _syscall2
- #define _syscall2(type, name, type1, arg1, type2, arg2) \
- type LSS_NAME(name)(type1 arg1, type2 arg2) { \
- LSS_BODY(2, type, name, arg1, arg2); \
- }
- #undef _syscall3
- #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
- LSS_BODY(3, type, name, arg1, arg2, arg3); \
- }
- #undef _syscall4
- #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
- type4, arg4) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- LSS_BODY(4, type, name, arg1, arg2, arg3, arg4); \
- }
- #undef _syscall5
- #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
- type4, arg4, type5, arg5) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5) { \
- LSS_BODY(5, type, name, arg1, arg2, arg3, arg4, arg5); \
- }
- #undef _syscall6
- #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
- type4, arg4, type5, arg5, type6, arg6) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5, type6 arg6) { \
- LSS_BODY(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \
- }
- /* clone function adapted from glibc 2.18 clone.S */
- LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
- int flags, void *arg, int *parent_tidptr,
- void *newtls, int *child_tidptr) {
- long __ret, __err;
- {
-#if defined(__PPC64__)
-
-/* Stack frame offsets. */
-#if _CALL_ELF != 2
-#define FRAME_MIN_SIZE 112
-#define FRAME_TOC_SAVE 40
-#else
-#define FRAME_MIN_SIZE 32
-#define FRAME_TOC_SAVE 24
-#endif
-
-
- register int (*__fn)(void *) __asm__ ("r3") = fn;
- register void *__cstack __asm__ ("r4") = child_stack;
- register int __flags __asm__ ("r5") = flags;
- register void * __arg __asm__ ("r6") = arg;
- register int * __ptidptr __asm__ ("r7") = parent_tidptr;
- register void * __newtls __asm__ ("r8") = newtls;
- register int * __ctidptr __asm__ ("r9") = child_tidptr;
- __asm__ __volatile__(
- /* check for fn == NULL
- * and child_stack == NULL
- */
- "cmpdi cr0, %6, 0\n\t"
- "cmpdi cr1, %7, 0\n\t"
- "cror cr0*4+eq, cr1*4+eq, cr0*4+eq\n\t"
- "beq- cr0, 1f\n\t"
-
- /* set up stack frame for child */
- "clrrdi %7, %7, 4\n\t"
- "li 0, 0\n\t"
- "stdu 0, -%13(%7)\n\t"
-
- /* fn, arg, child_stack are saved acrVoss the syscall */
- "mr 28, %6\n\t"
- "mr 29, %7\n\t"
- "mr 27, %9\n\t"
-
- /* syscall
- r3 == flags
- r4 == child_stack
- r5 == parent_tidptr
- r6 == newtls
- r7 == child_tidptr */
- "mr 3, %8\n\t"
- "mr 5, %10\n\t"
- "mr 6, %11\n\t"
- "mr 7, %12\n\t"
- "li 0, %4\n\t"
- "sc\n\t"
-
- /* Test if syscall was successful */
- "cmpdi cr1, 3, 0\n\t"
- "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
- "bne- cr1, 1f\n\t"
-
- /* Do the function call */
- "std 2, %14(1)\n\t"
-#if _CALL_ELF != 2
- "ld 0, 0(28)\n\t"
- "ld 2, 8(28)\n\t"
- "mtctr 0\n\t"
-#else
- "mr 12, 28\n\t"
- "mtctr 12\n\t"
-#endif
- "mr 3, 27\n\t"
- "bctrl\n\t"
- "ld 2, %14(1)\n\t"
-
- /* Call _exit(r3) */
- "li 0, %5\n\t"
- "sc\n\t"
-
- /* Return to parent */
- "1:\n\t"
- "mr %0, 3\n\t"
- : "=r" (__ret), "=r" (__err)
- : "0" (-1), "i" (EINVAL),
- "i" (__NR_clone), "i" (__NR_exit),
- "r" (__fn), "r" (__cstack), "r" (__flags),
- "r" (__arg), "r" (__ptidptr), "r" (__newtls),
- "r" (__ctidptr), "i" (FRAME_MIN_SIZE), "i" (FRAME_TOC_SAVE)
- : "cr0", "cr1", "memory", "ctr",
- "r0", "r29", "r27", "r28");
-#else
- register int (*__fn)(void *) __asm__ ("r8") = fn;
- register void *__cstack __asm__ ("r4") = child_stack;
- register int __flags __asm__ ("r3") = flags;
- register void * __arg __asm__ ("r9") = arg;
- register int * __ptidptr __asm__ ("r5") = parent_tidptr;
- register void * __newtls __asm__ ("r6") = newtls;
- register int * __ctidptr __asm__ ("r7") = child_tidptr;
- __asm__ __volatile__(
- /* check for fn == NULL
- * and child_stack == NULL
- */
- "cmpwi cr0, %6, 0\n\t"
- "cmpwi cr1, %7, 0\n\t"
- "cror cr0*4+eq, cr1*4+eq, cr0*4+eq\n\t"
- "beq- cr0, 1f\n\t"
-
- /* set up stack frame for child */
- "clrrwi %7, %7, 4\n\t"
- "li 0, 0\n\t"
- "stwu 0, -16(%7)\n\t"
-
- /* fn, arg, child_stack are saved across the syscall: r28-30 */
- "mr 28, %6\n\t"
- "mr 29, %7\n\t"
- "mr 27, %9\n\t"
-
- /* syscall */
- "li 0, %4\n\t"
- /* flags already in r3
- * child_stack already in r4
- * ptidptr already in r5
- * newtls already in r6
- * ctidptr already in r7
- */
- "sc\n\t"
-
- /* Test if syscall was successful */
- "cmpwi cr1, 3, 0\n\t"
- "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
- "bne- cr1, 1f\n\t"
-
- /* Do the function call */
- "mtctr 28\n\t"
- "mr 3, 27\n\t"
- "bctrl\n\t"
-
- /* Call _exit(r3) */
- "li 0, %5\n\t"
- "sc\n\t"
-
- /* Return to parent */
- "1:\n"
- "mfcr %1\n\t"
- "mr %0, 3\n\t"
- : "=r" (__ret), "=r" (__err)
- : "0" (-1), "1" (EINVAL),
- "i" (__NR_clone), "i" (__NR_exit),
- "r" (__fn), "r" (__cstack), "r" (__flags),
- "r" (__arg), "r" (__ptidptr), "r" (__newtls),
- "r" (__ctidptr)
- : "cr0", "cr1", "memory", "ctr",
- "r0", "r29", "r27", "r28");
-
-#endif
- }
- LSS_RETURN(int, __ret, __err);
- }
- #elif defined(__aarch64__)
- #undef LSS_REG
- #define LSS_REG(r,a) register long __x##r __asm__("x"#r) = (long)a
- #undef LSS_BODY
- #define LSS_BODY(type,name,args...) \
- register long __res_x0 __asm__("x0"); \
- long __res; \
- __asm__ __volatile__ ("mov x8, %1\n" \
- "svc 0x0\n" \
- : "=r"(__res_x0) \
- : "i"(__NR_##name) , ## args \
- : "memory"); \
- __res = __res_x0; \
- LSS_RETURN(type, __res)
- #undef _syscall0
- #define _syscall0(type, name) \
- type LSS_NAME(name)(void) { \
- LSS_BODY(type, name); \
- }
- #undef _syscall1
- #define _syscall1(type, name, type1, arg1) \
- type LSS_NAME(name)(type1 arg1) { \
- LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__x0)); \
- }
- #undef _syscall2
- #define _syscall2(type, name, type1, arg1, type2, arg2) \
- type LSS_NAME(name)(type1 arg1, type2 arg2) { \
- LSS_REG(0, arg1); LSS_REG(1, arg2); \
- LSS_BODY(type, name, "r"(__x0), "r"(__x1)); \
- }
- #undef _syscall3
- #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
- LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
- LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2)); \
- }
- #undef _syscall4
- #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
- LSS_REG(3, arg4); \
- LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2), "r"(__x3)); \
- }
- #undef _syscall5
- #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5) { \
- LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
- LSS_REG(3, arg4); LSS_REG(4, arg5); \
- LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2), "r"(__x3), \
- "r"(__x4)); \
- }
- #undef _syscall6
- #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5,type6,arg6) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5, type6 arg6) { \
- LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
- LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \
- LSS_BODY(type, name, "r"(__x0), "r"(__x1), "x"(__x2), "r"(__x3), \
- "r"(__x4), "r"(__x5)); \
- }
- /* clone function adapted from glibc 2.18 clone.S */
- LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
- int flags, void *arg, int *parent_tidptr,
- void *newtls, int *child_tidptr) {
- long __res;
- {
- register int (*__fn)(void *) __asm__("x0") = fn;
- register void *__stack __asm__("x1") = child_stack;
- register int __flags __asm__("x2") = flags;
- register void *__arg __asm__("x3") = arg;
- register int *__ptid __asm__("x4") = parent_tidptr;
- register void *__tls __asm__("x5") = newtls;
- register int *__ctid __asm__("x6") = child_tidptr;
- __asm__ __volatile__(/* if (fn == NULL || child_stack == NULL)
- * return -EINVAL;
- */
- "cbz x0,1f\n"
- "cbz x1,1f\n"
-
- /* Push "arg" and "fn" onto the stack that will be
- * used by the child.
- */
- "stp x0,x3, [x1, #-16]!\n"
-
- "mov x0,x2\n" /* flags */
- "mov x2,x4\n" /* ptid */
- "mov x3,x5\n" /* tls */
- "mov x4,x6\n" /* ctid */
- "mov x8,%9\n" /* clone */
-
- "svc 0x0\n"
-
- /* if (%r0 != 0)
- * return %r0;
- */
- "cmp x0, #0\n"
- "bne 2f\n"
-
- /* In the child, now. Call "fn(arg)".
- */
- "ldp x1, x0, [sp], #16\n"
- "blr x1\n"
-
- /* Call _exit(%r0).
- */
- "mov x8, %10\n"
- "svc 0x0\n"
- "1:\n"
- "mov x8, %1\n"
- "2:\n"
- : "=r" (__res)
- : "i"(-EINVAL),
- "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),
- "r"(__ptid), "r"(__tls), "r"(__ctid),
- "i"(__NR_clone), "i"(__NR_exit)
- : "x30", "memory");
- }
- LSS_RETURN(int, __res);
- }
- #elif defined(__s390x__)
- #undef LSS_REG
- #define LSS_REG(r, a) register unsigned long __r##r __asm__("r"#r) = (unsigned long) a
- #undef LSS_BODY
- #define LSS_BODY(type, name, args...) \
- register long __res_r2 __asm__("r2"); \
- long __res; \
- __asm__ __volatile__ \
- ("lgfi %%r1, %1\n\t" \
- "svc 0\n\t" \
- : "=&r"(__res_r2) \
- : "i"(__NR_##name), ## args \
- : "r1", "memory"); \
- __res = __res_r2; \
- LSS_RETURN(type, __res)
- #undef _syscall0
- #define _syscall0(type, name) \
- type LSS_NAME(name)(void) { \
- LSS_BODY(type, name); \
- }
- #undef _syscall1
- #define _syscall1(type, name, type1, arg1) \
- type LSS_NAME(name)(type1 arg1) { \
- LSS_REG(2, arg1); \
- LSS_BODY(type, name, "0"(__r2)); \
- }
- #undef _syscall2
- #define _syscall2(type, name, type1, arg1, type2, arg2) \
- type LSS_NAME(name)(type1 arg1, type2 arg2) { \
- LSS_REG(2, arg1); LSS_REG(3, arg2); \
- LSS_BODY(type, name, "0"(__r2), "r"(__r3)); \
- }
- #undef _syscall3
- #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
- LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
- LSS_BODY(type, name, "0"(__r2), "r"(__r3), "r"(__r4)); \
- }
- #undef _syscall4
- #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
- type4, arg4) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \
- type4 arg4) { \
- LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
- LSS_REG(5, arg4); \
- LSS_BODY(type, name, "0"(__r2), "r"(__r3), "r"(__r4), \
- "r"(__r5)); \
- }
- #undef _syscall5
- #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
- type4, arg4, type5, arg5) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \
- type4 arg4, type5 arg5) { \
- LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
- LSS_REG(5, arg4); LSS_REG(6, arg5); \
- LSS_BODY(type, name, "0"(__r2), "r"(__r3), "r"(__r4), \
- "r"(__r5), "r"(__r6)); \
- }
- #undef _syscall6
- #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
- type4, arg4, type5, arg5, type6, arg6) \
- type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \
- type4 arg4, type5 arg5, type6 arg6) { \
- LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
- LSS_REG(5, arg4); LSS_REG(6, arg5); LSS_REG(7, arg6); \
- LSS_BODY(type, name, "0"(__r2), "r"(__r3), "r"(__r4), \
- "r"(__r5), "r"(__r6), "r"(__r7)); \
- }
- LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
- int flags, void *arg, int *parent_tidptr,
- void *newtls, int *child_tidptr) {
- long __ret;
- {
- register int (*__fn)(void *) __asm__ ("r1") = fn;
- register void *__cstack __asm__ ("r2") = child_stack;
- register int __flags __asm__ ("r3") = flags;
- register void *__arg __asm__ ("r0") = arg;
- register int *__ptidptr __asm__ ("r4") = parent_tidptr;
- register void *__newtls __asm__ ("r6") = newtls;
- register int *__ctidptr __asm__ ("r5") = child_tidptr;
- __asm__ __volatile__ (
- /* arg already in r0 */
- "ltgr %4, %4\n\t" /* check fn, which is already in r1 */
- "jz 1f\n\t" /* NULL function pointer, return -EINVAL */
- "ltgr %5, %5\n\t" /* check child_stack, which is already in r2 */
- "jz 1f\n\t" /* NULL stack pointer, return -EINVAL */
- /* flags already in r3 */
- /* parent_tidptr already in r4 */
- /* child_tidptr already in r5 */
- /* newtls already in r6 */
- "svc %2\n\t" /* invoke clone syscall */
- "ltgr %0, %%r2\n\t" /* load return code into __ret and test */
- "jnz 1f\n\t" /* return to parent if non-zero */
- /* start child thread */
- "lgr %%r2, %7\n\t" /* set first parameter to void *arg */
- "aghi %%r15, -160\n\t" /* make room on the stack for the save area */
- "xc 0(8,%%r15), 0(%%r15)\n\t"
- "basr %%r14, %4\n\t" /* jump to fn */
- "svc %3\n" /* invoke exit syscall */
-
- "1:\n"
- : "=r" (__ret)
- : "0" (-EINVAL), "i" (__NR_clone), "i" (__NR_exit),
- "r" (__fn), "r" (__cstack), "r" (__flags), "r" (__arg),
- "r" (__ptidptr), "r" (__newtls), "r" (__ctidptr)
- : "cc", "r14", "memory"
- );
- }
- LSS_RETURN(int, __ret);
- }
- #endif
- #define __NR__exit __NR_exit
- #define __NR__gettid __NR_gettid
- #define __NR__mremap __NR_mremap
- LSS_INLINE _syscall1(int, close, int, f)
- LSS_INLINE _syscall1(int, _exit, int, e)
- LSS_INLINE _syscall3(int, fcntl, int, f,
- int, c, long, a)
- LSS_INLINE _syscall2(int, fstat, int, f,
- struct kernel_stat*, b)
- LSS_INLINE _syscall6(int, futex, int*, a,
- int, o, int, v,
- struct kernel_timespec*, t,
- int*, a2,
- int, v3)
-#ifdef __NR_getdents64
- LSS_INLINE _syscall3(int, getdents64, int, f,
- struct kernel_dirent64*, d, int, c)
-#define KERNEL_DIRENT kernel_dirent64
-#define GETDENTS sys_getdents64
-#else
- LSS_INLINE _syscall3(int, getdents, int, f,
- struct kernel_dirent*, d, int, c)
-#define KERNEL_DIRENT kernel_dirent
-#define GETDENTS sys_getdents
-#endif
- LSS_INLINE _syscall0(pid_t, getpid)
- LSS_INLINE _syscall0(pid_t, getppid)
- LSS_INLINE _syscall0(pid_t, _gettid)
- LSS_INLINE _syscall2(int, kill, pid_t, p,
- int, s)
- #if defined(__x86_64__)
- /* Need to make sure off_t isn't truncated to 32-bits under x32. */
- LSS_INLINE off_t LSS_NAME(lseek)(int f, off_t o, int w) {
- _LSS_BODY(3, off_t, lseek, off_t, LSS_SYSCALL_ARG(f), (uint64_t)(o),
- LSS_SYSCALL_ARG(w));
- }
- #else
- LSS_INLINE _syscall3(off_t, lseek, int, f,
- off_t, o, int, w)
- #endif
- LSS_INLINE _syscall2(int, munmap, void*, s,
- size_t, l)
- LSS_INLINE _syscall5(void*, _mremap, void*, o,
- size_t, os, size_t, ns,
- unsigned long, f, void *, a)
- LSS_INLINE _syscall2(int, prctl, int, o,
- long, a)
- LSS_INLINE _syscall4(long, ptrace, int, r,
- pid_t, p, void *, a, void *, d)
- LSS_INLINE _syscall3(ssize_t, read, int, f,
- void *, b, size_t, c)
- LSS_INLINE _syscall4(int, rt_sigaction, int, s,
- const struct kernel_sigaction*, a,
- struct kernel_sigaction*, o, size_t, c)
- LSS_INLINE _syscall4(int, rt_sigprocmask, int, h,
- const struct kernel_sigset_t*, s,
- struct kernel_sigset_t*, o, size_t, c);
- LSS_INLINE _syscall0(int, sched_yield)
- LSS_INLINE _syscall2(int, sigaltstack, const stack_t*, s,
- const stack_t*, o)
- #if defined(__NR_fstatat)
- LSS_INLINE _syscall4(int, fstatat, int, d, const char *, p,
- struct kernel_stat*, b, int, flags)
- LSS_INLINE int LSS_NAME(stat)(const char* p, struct kernel_stat* b) {
- return LSS_NAME(fstatat)(AT_FDCWD,p,b,0);
- }
- #else
- LSS_INLINE _syscall2(int, stat, const char*, f,
- struct kernel_stat*, b)
- #endif
- LSS_INLINE _syscall3(ssize_t, write, int, f,
- const void *, b, size_t, c)
- #if defined(__NR_getcpu)
- LSS_INLINE _syscall3(long, getcpu, unsigned *, cpu,
- unsigned *, node, void *, unused);
- #endif
- #if defined(__x86_64__) || defined(__aarch64__) || \
- (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32)
- LSS_INLINE _syscall3(int, socket, int, d,
- int, t, int, p)
- #endif
- #if defined(__x86_64__) || defined(__s390x__)
- #if defined(__s390x__)
- LSS_INLINE _syscall1(void*, mmap, void*, a)
- #else
- /* Need to make sure __off64_t isn't truncated to 32-bits under x32. */
- LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
- __off64_t o) {
- LSS_BODY(6, void*, mmap, LSS_SYSCALL_ARG(s), LSS_SYSCALL_ARG(l),
- LSS_SYSCALL_ARG(p), LSS_SYSCALL_ARG(f),
- LSS_SYSCALL_ARG(d), (uint64_t)(o));
- }
- #endif
-
- LSS_INLINE int LSS_NAME(sigaction)(int signum,
- const struct kernel_sigaction *act,
- struct kernel_sigaction *oldact) {
- #if defined(__x86_64__)
- /* On x86_64, the kernel requires us to always set our own
- * SA_RESTORER in order to be able to return from a signal handler.
- * This function must have a "magic" signature that the "gdb"
- * (and maybe the kernel?) can recognize.
- */
- if (act != NULL && !(act->sa_flags & SA_RESTORER)) {
- struct kernel_sigaction a = *act;
- a.sa_flags |= SA_RESTORER;
- a.sa_restorer = LSS_NAME(restore_rt)();
- return LSS_NAME(rt_sigaction)(signum, &a, oldact,
- (KERNEL_NSIG+7)/8);
- } else
- #endif
- {
- return LSS_NAME(rt_sigaction)(signum, act, oldact,
- (KERNEL_NSIG+7)/8);
- }
- }
-
- LSS_INLINE int LSS_NAME(sigprocmask)(int how,
- const struct kernel_sigset_t *set,
- struct kernel_sigset_t *oldset) {
- return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8);
- }
- #endif
- #if (defined(__aarch64__)) || \
- (defined(__mips__) && (_MIPS_ISA == _MIPS_ISA_MIPS64))
- LSS_INLINE _syscall6(void*, mmap, void*, s,
- size_t, l, int, p,
- int, f, int, d,
- __off64_t, o)
- LSS_INLINE int LSS_NAME(sigaction)(int signum,
- const struct kernel_sigaction *act,
- struct kernel_sigaction *oldact) {
- return LSS_NAME(rt_sigaction)(signum, act, oldact, (KERNEL_NSIG+7)/8);
-
- }
- LSS_INLINE int LSS_NAME(sigprocmask)(int how,
- const struct kernel_sigset_t *set,
- struct kernel_sigset_t *oldset) {
- return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8);
- }
- #endif
- #ifdef __NR_wait4
- LSS_INLINE _syscall4(pid_t, wait4, pid_t, p,
- int*, s, int, o,
- struct kernel_rusage*, r)
- LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options){
- return LSS_NAME(wait4)(pid, status, options, 0);
- }
- #else
- LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p,
- int*, s, int, o)
- #endif
- #ifdef __NR_openat
- LSS_INLINE _syscall4(int, openat, int, d, const char *, p, int, f, int, m)
- LSS_INLINE int LSS_NAME(open)(const char* p, int f, int m) {
- return LSS_NAME(openat)(AT_FDCWD,p,f,m );
- }
- #else
- LSS_INLINE _syscall3(int, open, const char*, p,
- int, f, int, m)
- #endif
- LSS_INLINE int LSS_NAME(sigemptyset)(struct kernel_sigset_t *set) {
- memset(&set->sig, 0, sizeof(set->sig));
- return 0;
- }
-
- LSS_INLINE int LSS_NAME(sigfillset)(struct kernel_sigset_t *set) {
- memset(&set->sig, -1, sizeof(set->sig));
- return 0;
- }
-
- LSS_INLINE int LSS_NAME(sigaddset)(struct kernel_sigset_t *set,
- int signum) {
- if (signum < 1 || signum > (int)(8*sizeof(set->sig))) {
- LSS_ERRNO = EINVAL;
- return -1;
- } else {
- set->sig[(signum - 1)/(8*sizeof(set->sig[0]))]
- |= 1UL << ((signum - 1) % (8*sizeof(set->sig[0])));
- return 0;
- }
- }
-
- LSS_INLINE int LSS_NAME(sigdelset)(struct kernel_sigset_t *set,
- int signum) {
- if (signum < 1 || signum > (int)(8*sizeof(set->sig))) {
- LSS_ERRNO = EINVAL;
- return -1;
- } else {
- set->sig[(signum - 1)/(8*sizeof(set->sig[0]))]
- &= ~(1UL << ((signum - 1) % (8*sizeof(set->sig[0]))));
- return 0;
- }
- }
-
- #if defined(__i386__) || \
- defined(__arm__) || \
- (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || defined(__PPC__)
- #define __NR__sigaction __NR_sigaction
- #define __NR__sigprocmask __NR_sigprocmask
- LSS_INLINE _syscall2(int, fstat64, int, f,
- struct kernel_stat64 *, b)
- LSS_INLINE _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
- loff_t *, res, uint, wh)
-#ifdef __PPC64__
- LSS_INLINE _syscall6(void*, mmap, void*, s,
- size_t, l, int, p,
- int, f, int, d,
- off_t, o)
-#else
- #ifndef __ARM_EABI__
- /* Not available on ARM EABI Linux. */
- LSS_INLINE _syscall1(void*, mmap, void*, a)
- #endif
- LSS_INLINE _syscall6(void*, mmap2, void*, s,
- size_t, l, int, p,
- int, f, int, d,
- off_t, o)
-#endif
- LSS_INLINE _syscall3(int, _sigaction, int, s,
- const struct kernel_old_sigaction*, a,
- struct kernel_old_sigaction*, o)
- LSS_INLINE _syscall3(int, _sigprocmask, int, h,
- const unsigned long*, s,
- unsigned long*, o)
- LSS_INLINE _syscall2(int, stat64, const char *, p,
- struct kernel_stat64 *, b)
-
- LSS_INLINE int LSS_NAME(sigaction)(int signum,
- const struct kernel_sigaction *act,
- struct kernel_sigaction *oldact) {
- int old_errno = LSS_ERRNO;
- int rc;
- struct kernel_sigaction a;
- if (act != NULL) {
- a = *act;
- #ifdef __i386__
- /* On i386, the kernel requires us to always set our own
- * SA_RESTORER when using realtime signals. Otherwise, it does not
- * know how to return from a signal handler. This function must have
- * a "magic" signature that the "gdb" (and maybe the kernel?) can
- * recognize.
- * Apparently, a SA_RESTORER is implicitly set by the kernel, when
- * using non-realtime signals.
- *
- * TODO: Test whether ARM needs a restorer
- */
- if (!(a.sa_flags & SA_RESTORER)) {
- a.sa_flags |= SA_RESTORER;
- a.sa_restorer = (a.sa_flags & SA_SIGINFO)
- ? LSS_NAME(restore_rt)() : LSS_NAME(restore)();
- }
- #endif
- }
- rc = LSS_NAME(rt_sigaction)(signum, act ? &a : act, oldact,
- (KERNEL_NSIG+7)/8);
- if (rc < 0 && LSS_ERRNO == ENOSYS) {
- struct kernel_old_sigaction oa, ooa, *ptr_a = &oa, *ptr_oa = &ooa;
- if (!act) {
- ptr_a = NULL;
- } else {
- oa.sa_handler_ = act->sa_handler_;
- memcpy(&oa.sa_mask, &act->sa_mask, sizeof(oa.sa_mask));
- #ifndef __mips__
- oa.sa_restorer = act->sa_restorer;
- #endif
- oa.sa_flags = act->sa_flags;
- }
- if (!oldact) {
- ptr_oa = NULL;
- }
- LSS_ERRNO = old_errno;
- rc = LSS_NAME(_sigaction)(signum, ptr_a, ptr_oa);
- if (rc == 0 && oldact) {
- if (act) {
- memcpy(oldact, act, sizeof(*act));
- } else {
- memset(oldact, 0, sizeof(*oldact));
- }
- oldact->sa_handler_ = ptr_oa->sa_handler_;
- oldact->sa_flags = ptr_oa->sa_flags;
- memcpy(&oldact->sa_mask, &ptr_oa->sa_mask, sizeof(ptr_oa->sa_mask));
- #ifndef __mips__
- oldact->sa_restorer = ptr_oa->sa_restorer;
- #endif
- }
- }
- return rc;
- }
-
- LSS_INLINE int LSS_NAME(sigprocmask)(int how,
- const struct kernel_sigset_t *set,
- struct kernel_sigset_t *oldset) {
- int olderrno = LSS_ERRNO;
- int rc = LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8);
- if (rc < 0 && LSS_ERRNO == ENOSYS) {
- LSS_ERRNO = olderrno;
- if (oldset) {
- LSS_NAME(sigemptyset)(oldset);
- }
- rc = LSS_NAME(_sigprocmask)(how,
- set ? &set->sig[0] : NULL,
- oldset ? &oldset->sig[0] : NULL);
- }
- return rc;
- }
- #endif
- #if defined(__i386__) || \
- defined(__PPC__) || \
- (defined(__arm__) && !defined(__ARM_EABI__)) || \
- (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
- defined(__s390x__)
-
- /* See sys_socketcall in net/socket.c in kernel source.
- * It de-multiplexes on its first arg and unpacks the arglist
- * array in its second arg.
- */
- LSS_INLINE _syscall2(int, socketcall, int, c, unsigned long*, a)
-
- LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) {
- unsigned long args[3] = {
- (unsigned long) domain,
- (unsigned long) type,
- (unsigned long) protocol
- };
- return LSS_NAME(socketcall)(1, args);
- }
- #elif defined(__ARM_EABI__)
- LSS_INLINE _syscall3(int, socket, int, d,
- int, t, int, p)
- #endif
- #if defined(__mips__)
- /* sys_pipe() on MIPS has non-standard calling conventions, as it returns
- * both file handles through CPU registers.
- */
- LSS_INLINE int LSS_NAME(pipe)(int *p) {
- register unsigned long __v0 __asm__("$2") = __NR_pipe;
- register unsigned long __v1 __asm__("$3");
- register unsigned long __r7 __asm__("$7");
- __asm__ __volatile__ ("syscall\n"
- : "=&r"(__v0), "=&r"(__v1), "+r" (__r7)
- : "0"(__v0)
- : "$8", "$9", "$10", "$11", "$12",
- "$13", "$14", "$15", "$24", "memory");
- if (__r7) {
- LSS_ERRNO = __v0;
- return -1;
- } else {
- p[0] = __v0;
- p[1] = __v1;
- return 0;
- }
- }
- #elif defined(__NR_pipe2)
- LSS_INLINE _syscall2(int, pipe2, int *, p,
- int, f )
- LSS_INLINE int LSS_NAME(pipe)( int * p) {
- return LSS_NAME(pipe2)(p, 0);
- }
- #else
- LSS_INLINE _syscall1(int, pipe, int *, p)
- #endif
-
- LSS_INLINE pid_t LSS_NAME(gettid)() {
- pid_t tid = LSS_NAME(_gettid)();
- if (tid != -1) {
- return tid;
- }
- return LSS_NAME(getpid)();
- }
-
- LSS_INLINE void *LSS_NAME(mremap)(void *old_address, size_t old_size,
- size_t new_size, int flags, ...) {
- va_list ap;
- void *new_address, *rc;
- va_start(ap, flags);
- new_address = va_arg(ap, void *);
- rc = LSS_NAME(_mremap)(old_address, old_size, new_size,
- flags, new_address);
- va_end(ap);
- return rc;
- }
-
- LSS_INLINE int LSS_NAME(ptrace_detach)(pid_t pid) {
- /* PTRACE_DETACH can sometimes forget to wake up the tracee and it
- * then sends job control signals to the real parent, rather than to
- * the tracer. We reduce the risk of this happening by starting a
- * whole new time slice, and then quickly sending a SIGCONT signal
- * right after detaching from the tracee.
- */
- int rc, err;
- LSS_NAME(sched_yield)();
- rc = LSS_NAME(ptrace)(PTRACE_DETACH, pid, (void *)0, (void *)0);
- err = LSS_ERRNO;
- LSS_NAME(kill)(pid, SIGCONT);
- LSS_ERRNO = err;
- return rc;
- }
-#endif
-
-#if defined(__cplusplus) && !defined(SYS_CPLUSPLUS)
-}
-#endif
-
-#endif
-#endif
diff --git a/src/third_party/gperftools-2.5/src/base/linuxthreads.cc b/src/third_party/gperftools-2.5/src/base/linuxthreads.cc
deleted file mode 100644
index 891e70c88c4..00000000000
--- a/src/third_party/gperftools-2.5/src/base/linuxthreads.cc
+++ /dev/null
@@ -1,707 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2005-2007, 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: Markus Gutschke
- */
-
-#include "base/linuxthreads.h"
-
-#ifdef THREADS
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sched.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <sys/prctl.h>
-#include <semaphore.h>
-
-#include "base/linux_syscall_support.h"
-#include "base/thread_lister.h"
-
-#ifndef CLONE_UNTRACED
-#define CLONE_UNTRACED 0x00800000
-#endif
-
-
-/* Synchronous signals that should not be blocked while in the lister thread.
- */
-static const int sync_signals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV, SIGBUS,
- SIGXCPU, SIGXFSZ };
-
-/* itoa() is not a standard function, and we cannot safely call printf()
- * after suspending threads. So, we just implement our own copy. A
- * recursive approach is the easiest here.
- */
-static char *local_itoa(char *buf, int i) {
- if (i < 0) {
- *buf++ = '-';
- return local_itoa(buf, -i);
- } else {
- if (i >= 10)
- buf = local_itoa(buf, i/10);
- *buf++ = (i%10) + '0';
- *buf = '\000';
- return buf;
- }
-}
-
-
-/* Wrapper around clone() that runs "fn" on the same stack as the
- * caller! Unlike fork(), the cloned thread shares the same address space.
- * The caller must be careful to use only minimal amounts of stack until
- * the cloned thread has returned.
- * There is a good chance that the cloned thread and the caller will share
- * the same copy of errno!
- */
-#ifdef __GNUC__
-#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1 || __GNUC__ > 3
-/* Try to force this function into a separate stack frame, and make sure
- * that arguments are passed on the stack.
- */
-static int local_clone (int (*fn)(void *), void *arg, ...)
- __attribute__ ((noinline));
-#endif
-#endif
-
-/* To avoid the gap cross page boundaries, increase by the large parge
- * size mostly PowerPC system uses. */
-#ifdef __PPC64__
-#define CLONE_STACK_SIZE 65536
-#else
-#define CLONE_STACK_SIZE 4096
-#endif
-
-static int local_clone (int (*fn)(void *), void *arg, ...) {
- /* Leave 4kB of gap between the callers stack and the new clone. This
- * should be more than sufficient for the caller to call waitpid() until
- * the cloned thread terminates.
- *
- * It is important that we set the CLONE_UNTRACED flag, because newer
- * versions of "gdb" otherwise attempt to attach to our thread, and will
- * attempt to reap its status codes. This subsequently results in the
- * caller hanging indefinitely in waitpid(), waiting for a change in
- * status that will never happen. By setting the CLONE_UNTRACED flag, we
- * prevent "gdb" from stealing events, but we still expect the thread
- * lister to fail, because it cannot PTRACE_ATTACH to the process that
- * is being debugged. This is OK and the error code will be reported
- * correctly.
- */
- return sys_clone(fn, (char *)&arg - CLONE_STACK_SIZE,
- CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_UNTRACED, arg, 0, 0, 0);
-}
-
-
-/* Local substitute for the atoi() function, which is not necessarily safe
- * to call once threads are suspended (depending on whether libc looks up
- * locale information, when executing atoi()).
- */
-static int local_atoi(const char *s) {
- int n = 0;
- int neg = *s == '-';
- if (neg)
- s++;
- while (*s >= '0' && *s <= '9')
- n = 10*n + (*s++ - '0');
- return neg ? -n : n;
-}
-
-
-/* Re-runs fn until it doesn't cause EINTR
- */
-#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR)
-
-
-/* Wrap a class around system calls, in order to give us access to
- * a private copy of errno. This only works in C++, but it has the
- * advantage of not needing nested functions, which are a non-standard
- * language extension.
- */
-#ifdef __cplusplus
-namespace {
- class SysCalls {
- public:
- #define SYS_CPLUSPLUS
- #define SYS_ERRNO my_errno
- #define SYS_INLINE inline
- #define SYS_PREFIX -1
- #undef SYS_LINUX_SYSCALL_SUPPORT_H
- #include "linux_syscall_support.h"
- SysCalls() : my_errno(0) { }
- int my_errno;
- };
-}
-#define ERRNO sys.my_errno
-#else
-#define ERRNO my_errno
-#endif
-
-
-/* Wrapper for open() which is guaranteed to never return EINTR.
- */
-static int c_open(const char *fname, int flags, int mode) {
- ssize_t rc;
- NO_INTR(rc = sys_open(fname, flags, mode));
- return rc;
-}
-
-
-/* abort() is not safely reentrant, and changes it's behavior each time
- * it is called. This means, if the main application ever called abort()
- * we cannot safely call it again. This would happen if we were called
- * from a SIGABRT signal handler in the main application. So, document
- * that calling SIGABRT from the thread lister makes it not signal safe
- * (and vice-versa).
- * Also, since we share address space with the main application, we
- * cannot call abort() from the callback and expect the main application
- * to behave correctly afterwards. In fact, the only thing we can do, is
- * to terminate the main application with extreme prejudice (aka
- * PTRACE_KILL).
- * We set up our own SIGABRT handler to do this.
- * In order to find the main application from the signal handler, we
- * need to store information about it in global variables. This is
- * safe, because the main application should be suspended at this
- * time. If the callback ever called TCMalloc_ResumeAllProcessThreads(), then
- * we are running a higher risk, though. So, try to avoid calling
- * abort() after calling TCMalloc_ResumeAllProcessThreads.
- */
-static volatile int *sig_pids, sig_num_threads, sig_proc, sig_marker;
-
-
-/* Signal handler to help us recover from dying while we are attached to
- * other threads.
- */
-static void SignalHandler(int signum, siginfo_t *si, void *data) {
- if (sig_pids != NULL) {
- if (signum == SIGABRT) {
- while (sig_num_threads-- > 0) {
- /* Not sure if sched_yield is really necessary here, but it does not */
- /* hurt, and it might be necessary for the same reasons that we have */
- /* to do so in sys_ptrace_detach(). */
- sys_sched_yield();
- sys_ptrace(PTRACE_KILL, sig_pids[sig_num_threads], 0, 0);
- }
- } else if (sig_num_threads > 0) {
- TCMalloc_ResumeAllProcessThreads(sig_num_threads, (int *)sig_pids);
- }
- }
- sig_pids = NULL;
- if (sig_marker >= 0)
- NO_INTR(sys_close(sig_marker));
- sig_marker = -1;
- if (sig_proc >= 0)
- NO_INTR(sys_close(sig_proc));
- sig_proc = -1;
-
- sys__exit(signum == SIGABRT ? 1 : 2);
-}
-
-
-/* Try to dirty the stack, and hope that the compiler is not smart enough
- * to optimize this function away. Or worse, the compiler could inline the
- * function and permanently allocate the data on the stack.
- */
-static void DirtyStack(size_t amount) {
- char buf[amount];
- memset(buf, 0, amount);
- sys_read(-1, buf, amount);
-}
-
-
-/* Data structure for passing arguments to the lister thread.
- */
-#define ALT_STACKSIZE (MINSIGSTKSZ + 4096)
-
-struct ListerParams {
- int result, err;
- char *altstack_mem;
- ListAllProcessThreadsCallBack callback;
- void *parameter;
- va_list ap;
- sem_t *lock;
-};
-
-
-static void ListerThread(struct ListerParams *args) {
- int found_parent = 0;
- pid_t clone_pid = sys_gettid(), ppid = sys_getppid();
- char proc_self_task[80], marker_name[48], *marker_path;
- const char *proc_paths[3];
- const char *const *proc_path = proc_paths;
- int proc = -1, marker = -1, num_threads = 0;
- int max_threads = 0, sig;
- struct kernel_stat marker_sb, proc_sb;
- stack_t altstack;
-
- /* Wait for parent thread to set appropriate permissions
- * to allow ptrace activity
- */
- if (sem_wait(args->lock) < 0) {
- goto failure;
- }
-
- /* Create "marker" that we can use to detect threads sharing the same
- * address space and the same file handles. By setting the FD_CLOEXEC flag
- * we minimize the risk of misidentifying child processes as threads;
- * and since there is still a race condition, we will filter those out
- * later, anyway.
- */
- if ((marker = sys_socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0 ||
- sys_fcntl(marker, F_SETFD, FD_CLOEXEC) < 0) {
- failure:
- args->result = -1;
- args->err = errno;
- if (marker >= 0)
- NO_INTR(sys_close(marker));
- sig_marker = marker = -1;
- if (proc >= 0)
- NO_INTR(sys_close(proc));
- sig_proc = proc = -1;
- sys__exit(1);
- }
-
- /* Compute search paths for finding thread directories in /proc */
- local_itoa(strrchr(strcpy(proc_self_task, "/proc/"), '\000'), ppid);
- strcpy(marker_name, proc_self_task);
- marker_path = marker_name + strlen(marker_name);
- strcat(proc_self_task, "/task/");
- proc_paths[0] = proc_self_task; /* /proc/$$/task/ */
- proc_paths[1] = "/proc/"; /* /proc/ */
- proc_paths[2] = NULL;
-
- /* Compute path for marker socket in /proc */
- local_itoa(strcpy(marker_path, "/fd/") + 4, marker);
- if (sys_stat(marker_name, &marker_sb) < 0) {
- goto failure;
- }
-
- /* Catch signals on an alternate pre-allocated stack. This way, we can
- * safely execute the signal handler even if we ran out of memory.
- */
- memset(&altstack, 0, sizeof(altstack));
- altstack.ss_sp = args->altstack_mem;
- altstack.ss_flags = 0;
- altstack.ss_size = ALT_STACKSIZE;
- sys_sigaltstack(&altstack, (const stack_t *)NULL);
-
- /* Some kernels forget to wake up traced processes, when the
- * tracer dies. So, intercept synchronous signals and make sure
- * that we wake up our tracees before dying. It is the caller's
- * responsibility to ensure that asynchronous signals do not
- * interfere with this function.
- */
- sig_marker = marker;
- sig_proc = -1;
- for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) {
- struct kernel_sigaction sa;
- memset(&sa, 0, sizeof(sa));
- sa.sa_sigaction_ = SignalHandler;
- sys_sigfillset(&sa.sa_mask);
- sa.sa_flags = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND;
- sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL);
- }
-
- /* Read process directories in /proc/... */
- for (;;) {
- /* Some kernels know about threads, and hide them in "/proc"
- * (although they are still there, if you know the process
- * id). Threads are moved into a separate "task" directory. We
- * check there first, and then fall back on the older naming
- * convention if necessary.
- */
- if ((sig_proc = proc = c_open(*proc_path, O_RDONLY|O_DIRECTORY, 0)) < 0) {
- if (*++proc_path != NULL)
- continue;
- goto failure;
- }
- if (sys_fstat(proc, &proc_sb) < 0)
- goto failure;
-
- /* Since we are suspending threads, we cannot call any libc
- * functions that might acquire locks. Most notably, we cannot
- * call malloc(). So, we have to allocate memory on the stack,
- * instead. Since we do not know how much memory we need, we
- * make a best guess. And if we guessed incorrectly we retry on
- * a second iteration (by jumping to "detach_threads").
- *
- * Unless the number of threads is increasing very rapidly, we
- * should never need to do so, though, as our guestimate is very
- * conservative.
- */
- if (max_threads < proc_sb.st_nlink + 100)
- max_threads = proc_sb.st_nlink + 100;
-
- /* scope */ {
- pid_t pids[max_threads];
- int added_entries = 0;
- sig_num_threads = num_threads;
- sig_pids = pids;
- for (;;) {
- struct KERNEL_DIRENT *entry;
- char buf[4096];
- ssize_t nbytes = GETDENTS(proc, (struct KERNEL_DIRENT *)buf,
- sizeof(buf));
- if (nbytes < 0)
- goto failure;
- else if (nbytes == 0) {
- if (added_entries) {
- /* Need to keep iterating over "/proc" in multiple
- * passes until we no longer find any more threads. This
- * algorithm eventually completes, when all threads have
- * been suspended.
- */
- added_entries = 0;
- sys_lseek(proc, 0, SEEK_SET);
- continue;
- }
- break;
- }
- for (entry = (struct KERNEL_DIRENT *)buf;
- entry < (struct KERNEL_DIRENT *)&buf[nbytes];
- entry = (struct KERNEL_DIRENT *)((char *)entry+entry->d_reclen)) {
- if (entry->d_ino != 0) {
- const char *ptr = entry->d_name;
- pid_t pid;
-
- /* Some kernels hide threads by preceding the pid with a '.' */
- if (*ptr == '.')
- ptr++;
-
- /* If the directory is not numeric, it cannot be a
- * process/thread
- */
- if (*ptr < '0' || *ptr > '9')
- continue;
- pid = local_atoi(ptr);
-
- /* Attach (and suspend) all threads */
- if (pid && pid != clone_pid) {
- struct kernel_stat tmp_sb;
- char fname[entry->d_reclen + 48];
- strcat(strcat(strcpy(fname, "/proc/"),
- entry->d_name), marker_path);
-
- /* Check if the marker is identical to the one we created */
- if (sys_stat(fname, &tmp_sb) >= 0 &&
- marker_sb.st_ino == tmp_sb.st_ino) {
- long i, j;
-
- /* Found one of our threads, make sure it is no duplicate */
- for (i = 0; i < num_threads; i++) {
- /* Linear search is slow, but should not matter much for
- * the typically small number of threads.
- */
- if (pids[i] == pid) {
- /* Found a duplicate; most likely on second pass */
- goto next_entry;
- }
- }
-
- /* Check whether data structure needs growing */
- if (num_threads >= max_threads) {
- /* Back to square one, this time with more memory */
- NO_INTR(sys_close(proc));
- goto detach_threads;
- }
-
- /* Attaching to thread suspends it */
- pids[num_threads++] = pid;
- sig_num_threads = num_threads;
- if (sys_ptrace(PTRACE_ATTACH, pid, (void *)0,
- (void *)0) < 0) {
- /* If operation failed, ignore thread. Maybe it
- * just died? There might also be a race
- * condition with a concurrent core dumper or
- * with a debugger. In that case, we will just
- * make a best effort, rather than failing
- * entirely.
- */
- num_threads--;
- sig_num_threads = num_threads;
- goto next_entry;
- }
- while (sys_waitpid(pid, (int *)0, __WALL) < 0) {
- if (errno != EINTR) {
- sys_ptrace_detach(pid);
- num_threads--;
- sig_num_threads = num_threads;
- goto next_entry;
- }
- }
-
- if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j ||
- sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i != j) {
- /* Address spaces are distinct, even though both
- * processes show the "marker". This is probably
- * a forked child process rather than a thread.
- */
- sys_ptrace_detach(pid);
- num_threads--;
- sig_num_threads = num_threads;
- } else {
- found_parent |= pid == ppid;
- added_entries++;
- }
- }
- }
- }
- next_entry:;
- }
- }
- NO_INTR(sys_close(proc));
- sig_proc = proc = -1;
-
- /* If we failed to find any threads, try looking somewhere else in
- * /proc. Maybe, threads are reported differently on this system.
- */
- if (num_threads > 1 || !*++proc_path) {
- NO_INTR(sys_close(marker));
- sig_marker = marker = -1;
-
- /* If we never found the parent process, something is very wrong.
- * Most likely, we are running in debugger. Any attempt to operate
- * on the threads would be very incomplete. Let's just report an
- * error to the caller.
- */
- if (!found_parent) {
- TCMalloc_ResumeAllProcessThreads(num_threads, pids);
- sys__exit(3);
- }
-
- /* Now we are ready to call the callback,
- * which takes care of resuming the threads for us.
- */
- args->result = args->callback(args->parameter, num_threads,
- pids, args->ap);
- args->err = errno;
-
- /* Callback should have resumed threads, but better safe than sorry */
- if (TCMalloc_ResumeAllProcessThreads(num_threads, pids)) {
- /* Callback forgot to resume at least one thread, report error */
- args->err = EINVAL;
- args->result = -1;
- }
-
- sys__exit(0);
- }
- detach_threads:
- /* Resume all threads prior to retrying the operation */
- TCMalloc_ResumeAllProcessThreads(num_threads, pids);
- sig_pids = NULL;
- num_threads = 0;
- sig_num_threads = num_threads;
- max_threads += 100;
- }
- }
-}
-
-
-/* This function gets the list of all linux threads of the current process
- * passes them to the 'callback' along with the 'parameter' pointer; at the
- * call back call time all the threads are paused via
- * PTRACE_ATTACH.
- * The callback is executed from a separate thread which shares only the
- * address space, the filesystem, and the filehandles with the caller. Most
- * notably, it does not share the same pid and ppid; and if it terminates,
- * the rest of the application is still there. 'callback' is supposed to do
- * or arrange for TCMalloc_ResumeAllProcessThreads. This happens automatically, if
- * the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous
- * signals are blocked. If the 'callback' decides to unblock them, it must
- * ensure that they cannot terminate the application, or that
- * TCMalloc_ResumeAllProcessThreads will get called.
- * It is an error for the 'callback' to make any library calls that could
- * acquire locks. Most notably, this means that most system calls have to
- * avoid going through libc. Also, this means that it is not legal to call
- * exit() or abort().
- * We return -1 on error and the return value of 'callback' on success.
- */
-int TCMalloc_ListAllProcessThreads(void *parameter,
- ListAllProcessThreadsCallBack callback, ...) {
- char altstack_mem[ALT_STACKSIZE];
- struct ListerParams args;
- pid_t clone_pid;
- int dumpable = 1, sig;
- struct kernel_sigset_t sig_blocked, sig_old;
- sem_t lock;
-
- va_start(args.ap, callback);
-
- /* If we are short on virtual memory, initializing the alternate stack
- * might trigger a SIGSEGV. Let's do this early, before it could get us
- * into more trouble (i.e. before signal handlers try to use the alternate
- * stack, and before we attach to other threads).
- */
- memset(altstack_mem, 0, sizeof(altstack_mem));
-
- /* Some of our cleanup functions could conceivable use more stack space.
- * Try to touch the stack right now. This could be defeated by the compiler
- * being too smart for it's own good, so try really hard.
- */
- DirtyStack(32768);
-
- /* Make this process "dumpable". This is necessary in order to ptrace()
- * after having called setuid().
- */
- dumpable = sys_prctl(PR_GET_DUMPABLE, 0);
- if (!dumpable)
- sys_prctl(PR_SET_DUMPABLE, 1);
-
- /* Fill in argument block for dumper thread */
- args.result = -1;
- args.err = 0;
- args.altstack_mem = altstack_mem;
- args.parameter = parameter;
- args.callback = callback;
- args.lock = &lock;
-
- /* Before cloning the thread lister, block all asynchronous signals, as we */
- /* are not prepared to handle them. */
- sys_sigfillset(&sig_blocked);
- for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) {
- sys_sigdelset(&sig_blocked, sync_signals[sig]);
- }
- if (sys_sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old)) {
- args.err = errno;
- args.result = -1;
- goto failed;
- }
-
- /* scope */ {
- /* After cloning, both the parent and the child share the same instance
- * of errno. We must make sure that at least one of these processes
- * (in our case, the parent) uses modified syscall macros that update
- * a local copy of errno, instead.
- */
- #ifdef __cplusplus
- #define sys0_sigprocmask sys.sigprocmask
- #define sys0_waitpid sys.waitpid
- SysCalls sys;
- #else
- int my_errno;
- #define SYS_ERRNO my_errno
- #define SYS_INLINE inline
- #define SYS_PREFIX 0
- #undef SYS_LINUX_SYSCALL_SUPPORT_H
- #include "linux_syscall_support.h"
- #endif
-
- /* Lock before clone so that parent can set
- * ptrace permissions (if necessary) prior
- * to ListerThread actually executing
- */
- if (sem_init(&lock, 0, 0) == 0) {
-
- int clone_errno;
- clone_pid = local_clone((int (*)(void *))ListerThread, &args);
- clone_errno = errno;
-
- sys_sigprocmask(SIG_SETMASK, &sig_old, &sig_old);
-
- if (clone_pid >= 0) {
-#ifdef PR_SET_PTRACER
- /* In newer versions of glibc permission must explicitly
- * be given to allow for ptrace.
- */
- prctl(PR_SET_PTRACER, clone_pid, 0, 0, 0);
-#endif
- /* Releasing the lock here allows the
- * ListerThread to execute and ptrace us.
- */
- sem_post(&lock);
- int status, rc;
- while ((rc = sys0_waitpid(clone_pid, &status, __WALL)) < 0 &&
- ERRNO == EINTR) {
- /* Keep waiting */
- }
- if (rc < 0) {
- args.err = ERRNO;
- args.result = -1;
- } else if (WIFEXITED(status)) {
- switch (WEXITSTATUS(status)) {
- case 0: break; /* Normal process termination */
- case 2: args.err = EFAULT; /* Some fault (e.g. SIGSEGV) detected */
- args.result = -1;
- break;
- case 3: args.err = EPERM; /* Process is already being traced */
- args.result = -1;
- break;
- default:args.err = ECHILD; /* Child died unexpectedly */
- args.result = -1;
- break;
- }
- } else if (!WIFEXITED(status)) {
- args.err = EFAULT; /* Terminated due to an unhandled signal*/
- args.result = -1;
- }
- sem_destroy(&lock);
- } else {
- args.result = -1;
- args.err = clone_errno;
- }
- } else {
- args.result = -1;
- args.err = errno;
- }
- }
-
- /* Restore the "dumpable" state of the process */
-failed:
- if (!dumpable)
- sys_prctl(PR_SET_DUMPABLE, dumpable);
-
- va_end(args.ap);
-
- errno = args.err;
- return args.result;
-}
-
-/* This function resumes the list of all linux threads that
- * TCMalloc_ListAllProcessThreads pauses before giving to its callback.
- * The function returns non-zero if at least one thread was
- * suspended and has now been resumed.
- */
-int TCMalloc_ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) {
- int detached_at_least_one = 0;
- while (num_threads-- > 0) {
- detached_at_least_one |= sys_ptrace_detach(thread_pids[num_threads]) >= 0;
- }
- return detached_at_least_one;
-}
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/third_party/gperftools-2.5/src/base/linuxthreads.h b/src/third_party/gperftools-2.5/src/base/linuxthreads.h
deleted file mode 100644
index 82965af905d..00000000000
--- a/src/third_party/gperftools-2.5/src/base/linuxthreads.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (c) 2005-2007, 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: Markus Gutschke
- */
-
-#ifndef _LINUXTHREADS_H
-#define _LINUXTHREADS_H
-
-/* Include thread_lister.h to get the interface that we implement for linux.
- */
-
-/* We currently only support x86-32 and x86-64 on Linux. Porting to other
- * related platforms should not be difficult.
- */
-#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
- defined(__mips__) || defined(__PPC__) || defined(__aarch64__) || \
- defined(__s390x__)) && defined(__linux)
-
-/* Define the THREADS symbol to make sure that there is exactly one core dumper
- * built into the library.
- */
-#define THREADS "Linux /proc"
-
-#endif
-
-#endif /* _LINUXTHREADS_H */
diff --git a/src/third_party/gperftools-2.5/src/base/logging.cc b/src/third_party/gperftools-2.5/src/base/logging.cc
deleted file mode 100644
index 761c2fd582e..00000000000
--- a/src/third_party/gperftools-2.5/src/base/logging.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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.
-
-// ---
-// This file just provides storage for FLAGS_verbose.
-
-#include <config.h>
-#include "base/logging.h"
-#include "base/commandlineflags.h"
-
-DEFINE_int32(verbose, EnvToInt("PERFTOOLS_VERBOSE", 0),
- "Set to numbers >0 for more verbose output, or <0 for less. "
- "--verbose == -4 means we log fatal errors only.");
-
-
-#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
-
-// While windows does have a POSIX-compatible API
-// (_open/_write/_close), it acquires memory. Using this lower-level
-// windows API is the closest we can get to being "raw".
-RawFD RawOpenForWriting(const char* filename) {
- // CreateFile allocates memory if file_name isn't absolute, so if
- // that ever becomes a problem then we ought to compute the absolute
- // path on its behalf (perhaps the ntdll/kernel function isn't aware
- // of the working directory?)
- RawFD fd = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, 0, NULL);
- if (fd != kIllegalRawFD && GetLastError() == ERROR_ALREADY_EXISTS)
- SetEndOfFile(fd); // truncate the existing file
- return fd;
-}
-
-void RawWrite(RawFD handle, const char* buf, size_t len) {
- while (len > 0) {
- DWORD wrote;
- BOOL ok = WriteFile(handle, buf, len, &wrote, NULL);
- // We do not use an asynchronous file handle, so ok==false means an error
- if (!ok) break;
- buf += wrote;
- len -= wrote;
- }
-}
-
-void RawClose(RawFD handle) {
- CloseHandle(handle);
-}
-
-#else // _WIN32 || __CYGWIN__ || __CYGWIN32__
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-// Re-run fn until it doesn't cause EINTR.
-#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR)
-
-RawFD RawOpenForWriting(const char* filename) {
- return open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0664);
-}
-
-void RawWrite(RawFD fd, const char* buf, size_t len) {
- while (len > 0) {
- ssize_t r;
- NO_INTR(r = write(fd, buf, len));
- if (r <= 0) break;
- buf += r;
- len -= r;
- }
-}
-
-void RawClose(RawFD fd) {
- NO_INTR(close(fd));
-}
-
-#endif // _WIN32 || __CYGWIN__ || __CYGWIN32__
diff --git a/src/third_party/gperftools-2.5/src/base/logging.h b/src/third_party/gperftools-2.5/src/base/logging.h
deleted file mode 100644
index a1afe4dca6e..00000000000
--- a/src/third_party/gperftools-2.5/src/base/logging.h
+++ /dev/null
@@ -1,259 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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.
-
-// ---
-// This file contains #include information about logging-related stuff.
-// Pretty much everybody needs to #include this file so that they can
-// log various happenings.
-//
-#ifndef _LOGGING_H_
-#define _LOGGING_H_
-
-#include <config.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for write()
-#endif
-#include <string.h> // for strlen(), strcmp()
-#include <assert.h>
-#include <errno.h> // for errno
-#include "base/commandlineflags.h"
-
-// On some systems (like freebsd), we can't call write() at all in a
-// global constructor, perhaps because errno hasn't been set up.
-// (In windows, we can't call it because it might call malloc.)
-// Calling the write syscall is safer (it doesn't set errno), so we
-// prefer that. Note we don't care about errno for logging: we just
-// do logging on a best-effort basis.
-#if defined(_MSC_VER)
-#define WRITE_TO_STDERR(buf, len) WriteToStderr(buf, len); // in port.cc
-#elif defined(HAVE_SYS_SYSCALL_H)
-#include <sys/syscall.h>
-#define WRITE_TO_STDERR(buf, len) syscall(SYS_write, STDERR_FILENO, buf, len)
-#else
-#define WRITE_TO_STDERR(buf, len) write(STDERR_FILENO, buf, len)
-#endif
-
-// MSVC and mingw define their own, safe version of vnsprintf (the
-// windows one in broken) in port.cc. Everyone else can use the
-// version here. We had to give it a unique name for windows.
-#ifndef _WIN32
-# define perftools_vsnprintf vsnprintf
-#endif
-
-
-// We log all messages at this log-level and below.
-// INFO == -1, WARNING == -2, ERROR == -3, FATAL == -4
-DECLARE_int32(verbose);
-
-// CHECK dies with a fatal error if condition is not true. It is *not*
-// controlled by NDEBUG, so the check will be executed regardless of
-// compilation mode. Therefore, it is safe to do things like:
-// CHECK(fp->Write(x) == 4)
-// Note we use write instead of printf/puts to avoid the risk we'll
-// call malloc().
-#define CHECK(condition) \
- do { \
- if (!(condition)) { \
- WRITE_TO_STDERR("Check failed: " #condition "\n", \
- sizeof("Check failed: " #condition "\n")-1); \
- abort(); \
- } \
- } while (0)
-
-// This takes a message to print. The name is historical.
-#define RAW_CHECK(condition, message) \
- do { \
- if (!(condition)) { \
- WRITE_TO_STDERR("Check failed: " #condition ": " message "\n", \
- sizeof("Check failed: " #condition ": " message "\n")-1);\
- abort(); \
- } \
- } while (0)
-
-// This is like RAW_CHECK, but only in debug-mode
-#ifdef NDEBUG
-enum { DEBUG_MODE = 0 };
-#define RAW_DCHECK(condition, message)
-#else
-enum { DEBUG_MODE = 1 };
-#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message)
-#endif
-
-// This prints errno as well. Note we use write instead of printf/puts to
-// avoid the risk we'll call malloc().
-#define PCHECK(condition) \
- do { \
- if (!(condition)) { \
- const int err_no = errno; \
- WRITE_TO_STDERR("Check failed: " #condition ": ", \
- sizeof("Check failed: " #condition ": ")-1); \
- WRITE_TO_STDERR(strerror(err_no), strlen(strerror(err_no))); \
- WRITE_TO_STDERR("\n", sizeof("\n")-1); \
- abort(); \
- } \
- } while (0)
-
-// Helper macro for binary operators; prints the two values on error
-// Don't use this macro directly in your code, use CHECK_EQ et al below
-
-// WARNING: These don't compile correctly if one of the arguments is a pointer
-// and the other is NULL. To work around this, simply static_cast NULL to the
-// type of the desired pointer.
-
-// TODO(jandrews): Also print the values in case of failure. Requires some
-// sort of type-sensitive ToString() function.
-#define CHECK_OP(op, val1, val2) \
- do { \
- if (!((val1) op (val2))) { \
- fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
- abort(); \
- } \
- } while (0)
-
-#define CHECK_EQ(val1, val2) CHECK_OP(==, val1, val2)
-#define CHECK_NE(val1, val2) CHECK_OP(!=, val1, val2)
-#define CHECK_LE(val1, val2) CHECK_OP(<=, val1, val2)
-#define CHECK_LT(val1, val2) CHECK_OP(< , val1, val2)
-#define CHECK_GE(val1, val2) CHECK_OP(>=, val1, val2)
-#define CHECK_GT(val1, val2) CHECK_OP(> , val1, val2)
-
-// Synonyms for CHECK_* that are used in some unittests.
-#define EXPECT_EQ(val1, val2) CHECK_EQ(val1, val2)
-#define EXPECT_NE(val1, val2) CHECK_NE(val1, val2)
-#define EXPECT_LE(val1, val2) CHECK_LE(val1, val2)
-#define EXPECT_LT(val1, val2) CHECK_LT(val1, val2)
-#define EXPECT_GE(val1, val2) CHECK_GE(val1, val2)
-#define EXPECT_GT(val1, val2) CHECK_GT(val1, val2)
-#define ASSERT_EQ(val1, val2) EXPECT_EQ(val1, val2)
-#define ASSERT_NE(val1, val2) EXPECT_NE(val1, val2)
-#define ASSERT_LE(val1, val2) EXPECT_LE(val1, val2)
-#define ASSERT_LT(val1, val2) EXPECT_LT(val1, val2)
-#define ASSERT_GE(val1, val2) EXPECT_GE(val1, val2)
-#define ASSERT_GT(val1, val2) EXPECT_GT(val1, val2)
-// As are these variants.
-#define EXPECT_TRUE(cond) CHECK(cond)
-#define EXPECT_FALSE(cond) CHECK(!(cond))
-#define EXPECT_STREQ(a, b) CHECK(strcmp(a, b) == 0)
-#define ASSERT_TRUE(cond) EXPECT_TRUE(cond)
-#define ASSERT_FALSE(cond) EXPECT_FALSE(cond)
-#define ASSERT_STREQ(a, b) EXPECT_STREQ(a, b)
-
-// Used for (libc) functions that return -1 and set errno
-#define CHECK_ERR(invocation) PCHECK((invocation) != -1)
-
-// A few more checks that only happen in debug mode
-#ifdef NDEBUG
-#define DCHECK_EQ(val1, val2)
-#define DCHECK_NE(val1, val2)
-#define DCHECK_LE(val1, val2)
-#define DCHECK_LT(val1, val2)
-#define DCHECK_GE(val1, val2)
-#define DCHECK_GT(val1, val2)
-#else
-#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
-#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
-#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
-#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
-#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
-#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
-#endif
-
-
-#ifdef ERROR
-#undef ERROR // may conflict with ERROR macro on windows
-#endif
-enum LogSeverity {INFO = -1, WARNING = -2, ERROR = -3, FATAL = -4};
-
-// NOTE: we add a newline to the end of the output if it's not there already
-inline void LogPrintf(int severity, const char* pat, va_list ap) {
- // We write directly to the stderr file descriptor and avoid FILE
- // buffering because that may invoke malloc()
- char buf[600];
- perftools_vsnprintf(buf, sizeof(buf)-1, pat, ap);
- if (buf[0] != '\0' && buf[strlen(buf)-1] != '\n') {
- assert(strlen(buf)+1 < sizeof(buf));
- strcat(buf, "\n");
- }
- WRITE_TO_STDERR(buf, strlen(buf));
- if ((severity) == FATAL)
- abort(); // LOG(FATAL) indicates a big problem, so don't run atexit() calls
-}
-
-// Note that since the order of global constructors is unspecified,
-// global code that calls RAW_LOG may execute before FLAGS_verbose is set.
-// Such code will run with verbosity == 0 no matter what.
-#define VLOG_IS_ON(severity) (FLAGS_verbose >= severity)
-
-// In a better world, we'd use __VA_ARGS__, but VC++ 7 doesn't support it.
-#define LOG_PRINTF(severity, pat) do { \
- if (VLOG_IS_ON(severity)) { \
- va_list ap; \
- va_start(ap, pat); \
- LogPrintf(severity, pat, ap); \
- va_end(ap); \
- } \
-} while (0)
-
-// RAW_LOG is the main function; some synonyms are used in unittests.
-inline void RAW_LOG(int lvl, const char* pat, ...) { LOG_PRINTF(lvl, pat); }
-inline void RAW_VLOG(int lvl, const char* pat, ...) { LOG_PRINTF(lvl, pat); }
-inline void LOG(int lvl, const char* pat, ...) { LOG_PRINTF(lvl, pat); }
-inline void VLOG(int lvl, const char* pat, ...) { LOG_PRINTF(lvl, pat); }
-inline void LOG_IF(int lvl, bool cond, const char* pat, ...) {
- if (cond) LOG_PRINTF(lvl, pat);
-}
-
-// This isn't technically logging, but it's also IO and also is an
-// attempt to be "raw" -- that is, to not use any higher-level libc
-// routines that might allocate memory or (ideally) try to allocate
-// locks. We use an opaque file handle (not necessarily an int)
-// to allow even more low-level stuff in the future.
-// Like other "raw" routines, these functions are best effort, and
-// thus don't return error codes (except RawOpenForWriting()).
-#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
-#ifndef NOMINMAX
-#define NOMINMAX // @#!$& windows
-#endif
-#include <windows.h>
-typedef HANDLE RawFD;
-const RawFD kIllegalRawFD = INVALID_HANDLE_VALUE;
-#else
-typedef int RawFD;
-const RawFD kIllegalRawFD = -1; // what open returns if it fails
-#endif // defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
-
-RawFD RawOpenForWriting(const char* filename); // uses default permissions
-void RawWrite(RawFD fd, const char* buf, size_t len);
-void RawClose(RawFD fd);
-
-#endif // _LOGGING_H_
diff --git a/src/third_party/gperftools-2.5/src/base/low_level_alloc.cc b/src/third_party/gperftools-2.5/src/base/low_level_alloc.cc
deleted file mode 100644
index 6b467cff123..00000000000
--- a/src/third_party/gperftools-2.5/src/base/low_level_alloc.cc
+++ /dev/null
@@ -1,582 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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.
- */
-
-// A low-level allocator that can be used by other low-level
-// modules without introducing dependency cycles.
-// This allocator is slow and wasteful of memory;
-// it should not be used when performance is key.
-
-#include "base/low_level_alloc.h"
-#include "base/dynamic_annotations.h"
-#include "base/spinlock.h"
-#include "base/logging.h"
-#include "malloc_hook-inl.h"
-#include <gperftools/malloc_hook.h>
-#include <errno.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-#include <new> // for placement-new
-
-// 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
-
-// A first-fit allocator with amortized logarithmic free() time.
-
-LowLevelAlloc::PagesAllocator::~PagesAllocator() {
-}
-
-// ---------------------------------------------------------------------------
-static const int kMaxLevel = 30;
-
-// We put this class-only struct in a namespace to avoid polluting the
-// global namespace with this struct name (thus risking an ODR violation).
-namespace low_level_alloc_internal {
- // This struct describes one allocated block, or one free block.
- struct AllocList {
- struct Header {
- intptr_t size; // size of entire region, including this field. Must be
- // first. Valid in both allocated and unallocated blocks
- intptr_t magic; // kMagicAllocated or kMagicUnallocated xor this
- LowLevelAlloc::Arena *arena; // pointer to parent arena
- void *dummy_for_alignment; // aligns regions to 0 mod 2*sizeof(void*)
- } header;
-
- // Next two fields: in unallocated blocks: freelist skiplist data
- // in allocated blocks: overlaps with client data
- int levels; // levels in skiplist used
- AllocList *next[kMaxLevel]; // actually has levels elements.
- // The AllocList node may not have room for
- // all kMaxLevel entries. See max_fit in
- // LLA_SkiplistLevels()
- };
-}
-using low_level_alloc_internal::AllocList;
-
-
-// ---------------------------------------------------------------------------
-// A trivial skiplist implementation. This is used to keep the freelist
-// in address order while taking only logarithmic time per insert and delete.
-
-// An integer approximation of log2(size/base)
-// Requires size >= base.
-static int IntLog2(size_t size, size_t base) {
- int result = 0;
- for (size_t i = size; i > base; i >>= 1) { // i == floor(size/2**result)
- result++;
- }
- // floor(size / 2**result) <= base < floor(size / 2**(result-1))
- // => log2(size/(base+1)) <= result < 1+log2(size/base)
- // => result ~= log2(size/base)
- return result;
-}
-
-// Return a random integer n: p(n)=1/(2**n) if 1 <= n; p(n)=0 if n < 1.
-static int Random() {
- static uint32 r = 1; // no locking---it's not critical
- ANNOTATE_BENIGN_RACE(&r, "benign race, not critical.");
- int result = 1;
- while ((((r = r*1103515245 + 12345) >> 30) & 1) == 0) {
- result++;
- }
- return result;
-}
-
-// Return a number of skiplist levels for a node of size bytes, where
-// base is the minimum node size. Compute level=log2(size / base)+n
-// where n is 1 if random is false and otherwise a random number generated with
-// the standard distribution for a skiplist: See Random() above.
-// Bigger nodes tend to have more skiplist levels due to the log2(size / base)
-// term, so first-fit searches touch fewer nodes. "level" is clipped so
-// level<kMaxLevel and next[level-1] will fit in the node.
-// 0 < LLA_SkiplistLevels(x,y,false) <= LLA_SkiplistLevels(x,y,true) < kMaxLevel
-static int LLA_SkiplistLevels(size_t size, size_t base, bool random) {
- // max_fit is the maximum number of levels that will fit in a node for the
- // given size. We can't return more than max_fit, no matter what the
- // random number generator says.
- int max_fit = (size-OFFSETOF_MEMBER(AllocList, next)) / sizeof (AllocList *);
- int level = IntLog2(size, base) + (random? Random() : 1);
- if (level > max_fit) level = max_fit;
- if (level > kMaxLevel-1) level = kMaxLevel - 1;
- RAW_CHECK(level >= 1, "block not big enough for even one level");
- return level;
-}
-
-// Return "atleast", the first element of AllocList *head s.t. *atleast >= *e.
-// For 0 <= i < head->levels, set prev[i] to "no_greater", where no_greater
-// points to the last element at level i in the AllocList less than *e, or is
-// head if no such element exists.
-static AllocList *LLA_SkiplistSearch(AllocList *head,
- AllocList *e, AllocList **prev) {
- AllocList *p = head;
- for (int level = head->levels - 1; level >= 0; level--) {
- for (AllocList *n; (n = p->next[level]) != 0 && n < e; p = n) {
- }
- prev[level] = p;
- }
- return (head->levels == 0) ? 0 : prev[0]->next[0];
-}
-
-// Insert element *e into AllocList *head. Set prev[] as LLA_SkiplistSearch.
-// Requires that e->levels be previously set by the caller (using
-// LLA_SkiplistLevels())
-static void LLA_SkiplistInsert(AllocList *head, AllocList *e,
- AllocList **prev) {
- LLA_SkiplistSearch(head, e, prev);
- for (; head->levels < e->levels; head->levels++) { // extend prev pointers
- prev[head->levels] = head; // to all *e's levels
- }
- for (int i = 0; i != e->levels; i++) { // add element to list
- e->next[i] = prev[i]->next[i];
- prev[i]->next[i] = e;
- }
-}
-
-// Remove element *e from AllocList *head. Set prev[] as LLA_SkiplistSearch().
-// Requires that e->levels be previous set by the caller (using
-// LLA_SkiplistLevels())
-static void LLA_SkiplistDelete(AllocList *head, AllocList *e,
- AllocList **prev) {
- AllocList *found = LLA_SkiplistSearch(head, e, prev);
- RAW_CHECK(e == found, "element not in freelist");
- for (int i = 0; i != e->levels && prev[i]->next[i] == e; i++) {
- prev[i]->next[i] = e->next[i];
- }
- while (head->levels > 0 && head->next[head->levels - 1] == 0) {
- head->levels--; // reduce head->levels if level unused
- }
-}
-
-// ---------------------------------------------------------------------------
-// Arena implementation
-
-struct LowLevelAlloc::Arena {
- Arena() : mu(SpinLock::LINKER_INITIALIZED) {} // does nothing; for static init
- explicit Arena(int) : pagesize(0) {} // set pagesize to zero explicitly
- // for non-static init
-
- SpinLock mu; // protects freelist, allocation_count,
- // pagesize, roundup, min_size
- AllocList freelist; // head of free list; sorted by addr (under mu)
- int32 allocation_count; // count of allocated blocks (under mu)
- int32 flags; // flags passed to NewArena (ro after init)
- size_t pagesize; // ==getpagesize() (init under mu, then ro)
- size_t roundup; // lowest power of 2 >= max(16,sizeof (AllocList))
- // (init under mu, then ro)
- size_t min_size; // smallest allocation block size
- // (init under mu, then ro)
- PagesAllocator *allocator;
-};
-
-// The default arena, which is used when 0 is passed instead of an Arena
-// pointer.
-static struct LowLevelAlloc::Arena default_arena;
-
-// Non-malloc-hooked arenas: used only to allocate metadata for arenas that
-// do not want malloc hook reporting, so that for them there's no malloc hook
-// reporting even during arena creation.
-static struct LowLevelAlloc::Arena unhooked_arena;
-static struct LowLevelAlloc::Arena unhooked_async_sig_safe_arena;
-
-namespace {
-
- class DefaultPagesAllocator : public LowLevelAlloc::PagesAllocator {
- public:
- virtual ~DefaultPagesAllocator() {};
- virtual void *MapPages(int32 flags, size_t size);
- virtual void UnMapPages(int32 flags, void *addr, size_t size);
- };
-
-}
-
-// magic numbers to identify allocated and unallocated blocks
-static const intptr_t kMagicAllocated = 0x4c833e95;
-static const intptr_t kMagicUnallocated = ~kMagicAllocated;
-
-namespace {
- class SCOPED_LOCKABLE ArenaLock {
- public:
- explicit ArenaLock(LowLevelAlloc::Arena *arena)
- EXCLUSIVE_LOCK_FUNCTION(arena->mu)
- : left_(false), mask_valid_(false), arena_(arena) {
- if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
- // We've decided not to support async-signal-safe arena use until
- // there a demonstrated need. Here's how one could do it though
- // (would need to be made more portable).
-#if 0
- sigset_t all;
- sigfillset(&all);
- this->mask_valid_ =
- (pthread_sigmask(SIG_BLOCK, &all, &this->mask_) == 0);
-#else
- RAW_CHECK(false, "We do not yet support async-signal-safe arena.");
-#endif
- }
- this->arena_->mu.Lock();
- }
- ~ArenaLock() { RAW_CHECK(this->left_, "haven't left Arena region"); }
- void Leave() /*UNLOCK_FUNCTION()*/ {
- this->arena_->mu.Unlock();
-#if 0
- if (this->mask_valid_) {
- pthread_sigmask(SIG_SETMASK, &this->mask_, 0);
- }
-#endif
- this->left_ = true;
- }
- private:
- bool left_; // whether left region
- bool mask_valid_;
-#if 0
- sigset_t mask_; // old mask of blocked signals
-#endif
- LowLevelAlloc::Arena *arena_;
- DISALLOW_COPY_AND_ASSIGN(ArenaLock);
- };
-} // anonymous namespace
-
-// create an appropriate magic number for an object at "ptr"
-// "magic" should be kMagicAllocated or kMagicUnallocated
-inline static intptr_t Magic(intptr_t magic, AllocList::Header *ptr) {
- return magic ^ reinterpret_cast<intptr_t>(ptr);
-}
-
-// Initialize the fields of an Arena
-static void ArenaInit(LowLevelAlloc::Arena *arena) {
- if (arena->pagesize == 0) {
- arena->pagesize = getpagesize();
- // Round up block sizes to a power of two close to the header size.
- arena->roundup = 16;
- while (arena->roundup < sizeof (arena->freelist.header)) {
- arena->roundup += arena->roundup;
- }
- // Don't allocate blocks less than twice the roundup size to avoid tiny
- // free blocks.
- arena->min_size = 2 * arena->roundup;
- arena->freelist.header.size = 0;
- arena->freelist.header.magic =
- Magic(kMagicUnallocated, &arena->freelist.header);
- arena->freelist.header.arena = arena;
- arena->freelist.levels = 0;
- memset(arena->freelist.next, 0, sizeof (arena->freelist.next));
- arena->allocation_count = 0;
- if (arena == &default_arena) {
- // Default arena should be hooked, e.g. for heap-checker to trace
- // pointer chains through objects in the default arena.
- arena->flags = LowLevelAlloc::kCallMallocHook;
- } else if (arena == &unhooked_async_sig_safe_arena) {
- arena->flags = LowLevelAlloc::kAsyncSignalSafe;
- } else {
- arena->flags = 0; // other arenas' flags may be overridden by client,
- // but unhooked_arena will have 0 in 'flags'.
- }
- arena->allocator = LowLevelAlloc::GetDefaultPagesAllocator();
- }
-}
-
-// L < meta_data_arena->mu
-LowLevelAlloc::Arena *LowLevelAlloc::NewArena(int32 flags,
- Arena *meta_data_arena) {
- return NewArenaWithCustomAlloc(flags, meta_data_arena, NULL);
-}
-
-// L < meta_data_arena->mu
-LowLevelAlloc::Arena *LowLevelAlloc::NewArenaWithCustomAlloc(int32 flags,
- Arena *meta_data_arena,
- PagesAllocator *allocator) {
- RAW_CHECK(meta_data_arena != 0, "must pass a valid arena");
- if (meta_data_arena == &default_arena) {
- if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
- meta_data_arena = &unhooked_async_sig_safe_arena;
- } else if ((flags & LowLevelAlloc::kCallMallocHook) == 0) {
- meta_data_arena = &unhooked_arena;
- }
- }
- // Arena(0) uses the constructor for non-static contexts
- Arena *result =
- new (AllocWithArena(sizeof (*result), meta_data_arena)) Arena(0);
- ArenaInit(result);
- result->flags = flags;
- if (allocator) {
- result->allocator = allocator;
- }
- return result;
-}
-
-// L < arena->mu, L < arena->arena->mu
-bool LowLevelAlloc::DeleteArena(Arena *arena) {
- RAW_CHECK(arena != 0 && arena != &default_arena && arena != &unhooked_arena,
- "may not delete default arena");
- ArenaLock section(arena);
- bool empty = (arena->allocation_count == 0);
- section.Leave();
- if (empty) {
- while (arena->freelist.next[0] != 0) {
- AllocList *region = arena->freelist.next[0];
- size_t size = region->header.size;
- arena->freelist.next[0] = region->next[0];
- RAW_CHECK(region->header.magic ==
- Magic(kMagicUnallocated, &region->header),
- "bad magic number in DeleteArena()");
- RAW_CHECK(region->header.arena == arena,
- "bad arena pointer in DeleteArena()");
- RAW_CHECK(size % arena->pagesize == 0,
- "empty arena has non-page-aligned block size");
- RAW_CHECK(reinterpret_cast<intptr_t>(region) % arena->pagesize == 0,
- "empty arena has non-page-aligned block");
- int munmap_result;
- if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) == 0) {
- munmap_result = munmap(region, size);
- } else {
- munmap_result = MallocHook::UnhookedMUnmap(region, size);
- }
- RAW_CHECK(munmap_result == 0,
- "LowLevelAlloc::DeleteArena: munmap failed address");
- }
- Free(arena);
- }
- return empty;
-}
-
-// ---------------------------------------------------------------------------
-
-// Return value rounded up to next multiple of align.
-// align must be a power of two.
-static intptr_t RoundUp(intptr_t addr, intptr_t align) {
- return (addr + align - 1) & ~(align - 1);
-}
-
-// Equivalent to "return prev->next[i]" but with sanity checking
-// that the freelist is in the correct order, that it
-// consists of regions marked "unallocated", and that no two regions
-// are adjacent in memory (they should have been coalesced).
-// L < arena->mu
-static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena) {
- RAW_CHECK(i < prev->levels, "too few levels in Next()");
- AllocList *next = prev->next[i];
- if (next != 0) {
- RAW_CHECK(next->header.magic == Magic(kMagicUnallocated, &next->header),
- "bad magic number in Next()");
- RAW_CHECK(next->header.arena == arena,
- "bad arena pointer in Next()");
- if (prev != &arena->freelist) {
- RAW_CHECK(prev < next, "unordered freelist");
- RAW_CHECK(reinterpret_cast<char *>(prev) + prev->header.size <
- reinterpret_cast<char *>(next), "malformed freelist");
- }
- }
- return next;
-}
-
-// Coalesce list item "a" with its successor if they are adjacent.
-static void Coalesce(AllocList *a) {
- AllocList *n = a->next[0];
- if (n != 0 && reinterpret_cast<char *>(a) + a->header.size ==
- reinterpret_cast<char *>(n)) {
- LowLevelAlloc::Arena *arena = a->header.arena;
- a->header.size += n->header.size;
- n->header.magic = 0;
- n->header.arena = 0;
- AllocList *prev[kMaxLevel];
- LLA_SkiplistDelete(&arena->freelist, n, prev);
- LLA_SkiplistDelete(&arena->freelist, a, prev);
- a->levels = LLA_SkiplistLevels(a->header.size, arena->min_size, true);
- LLA_SkiplistInsert(&arena->freelist, a, prev);
- }
-}
-
-// Adds block at location "v" to the free list
-// L >= arena->mu
-static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena) {
- AllocList *f = reinterpret_cast<AllocList *>(
- reinterpret_cast<char *>(v) - sizeof (f->header));
- RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),
- "bad magic number in AddToFreelist()");
- RAW_CHECK(f->header.arena == arena,
- "bad arena pointer in AddToFreelist()");
- f->levels = LLA_SkiplistLevels(f->header.size, arena->min_size, true);
- AllocList *prev[kMaxLevel];
- LLA_SkiplistInsert(&arena->freelist, f, prev);
- f->header.magic = Magic(kMagicUnallocated, &f->header);
- Coalesce(f); // maybe coalesce with successor
- Coalesce(prev[0]); // maybe coalesce with predecessor
-}
-
-// Frees storage allocated by LowLevelAlloc::Alloc().
-// L < arena->mu
-void LowLevelAlloc::Free(void *v) {
- if (v != 0) {
- AllocList *f = reinterpret_cast<AllocList *>(
- reinterpret_cast<char *>(v) - sizeof (f->header));
- RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),
- "bad magic number in Free()");
- LowLevelAlloc::Arena *arena = f->header.arena;
- if ((arena->flags & kCallMallocHook) != 0) {
- MallocHook::InvokeDeleteHook(v);
- }
- ArenaLock section(arena);
- AddToFreelist(v, arena);
- RAW_CHECK(arena->allocation_count > 0, "nothing in arena to free");
- arena->allocation_count--;
- section.Leave();
- }
-}
-
-// allocates and returns a block of size bytes, to be freed with Free()
-// L < arena->mu
-static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
- void *result = 0;
- if (request != 0) {
- AllocList *s; // will point to region that satisfies request
- ArenaLock section(arena);
- ArenaInit(arena);
- // round up with header
- size_t req_rnd = RoundUp(request + sizeof (s->header), arena->roundup);
- for (;;) { // loop until we find a suitable region
- // find the minimum levels that a block of this size must have
- int i = LLA_SkiplistLevels(req_rnd, arena->min_size, false) - 1;
- if (i < arena->freelist.levels) { // potential blocks exist
- AllocList *before = &arena->freelist; // predecessor of s
- while ((s = Next(i, before, arena)) != 0 && s->header.size < req_rnd) {
- before = s;
- }
- if (s != 0) { // we found a region
- break;
- }
- }
- // we unlock before mmap() both because mmap() may call a callback hook,
- // and because it may be slow.
- arena->mu.Unlock();
- // mmap generous 64K chunks to decrease
- // the chances/impact of fragmentation:
- size_t new_pages_size = RoundUp(req_rnd, arena->pagesize * 16);
- void *new_pages = arena->allocator->MapPages(arena->flags, new_pages_size);
- arena->mu.Lock();
- s = reinterpret_cast<AllocList *>(new_pages);
- s->header.size = new_pages_size;
- // Pretend the block is allocated; call AddToFreelist() to free it.
- s->header.magic = Magic(kMagicAllocated, &s->header);
- s->header.arena = arena;
- AddToFreelist(&s->levels, arena); // insert new region into free list
- }
- AllocList *prev[kMaxLevel];
- LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list
- // s points to the first free region that's big enough
- if (req_rnd + arena->min_size <= s->header.size) { // big enough to split
- AllocList *n = reinterpret_cast<AllocList *>
- (req_rnd + reinterpret_cast<char *>(s));
- n->header.size = s->header.size - req_rnd;
- n->header.magic = Magic(kMagicAllocated, &n->header);
- n->header.arena = arena;
- s->header.size = req_rnd;
- AddToFreelist(&n->levels, arena);
- }
- s->header.magic = Magic(kMagicAllocated, &s->header);
- RAW_CHECK(s->header.arena == arena, "");
- arena->allocation_count++;
- section.Leave();
- result = &s->levels;
- }
- ANNOTATE_NEW_MEMORY(result, request);
- return result;
-}
-
-void *LowLevelAlloc::Alloc(size_t request) {
- void *result = DoAllocWithArena(request, &default_arena);
- if ((default_arena.flags & kCallMallocHook) != 0) {
- // this call must be directly in the user-called allocator function
- // for MallocHook::GetCallerStackTrace to work properly
- MallocHook::InvokeNewHook(result, request);
- }
- return result;
-}
-
-void *LowLevelAlloc::AllocWithArena(size_t request, Arena *arena) {
- RAW_CHECK(arena != 0, "must pass a valid arena");
- void *result = DoAllocWithArena(request, arena);
- if ((arena->flags & kCallMallocHook) != 0) {
- // this call must be directly in the user-called allocator function
- // for MallocHook::GetCallerStackTrace to work properly
- MallocHook::InvokeNewHook(result, request);
- }
- return result;
-}
-
-LowLevelAlloc::Arena *LowLevelAlloc::DefaultArena() {
- return &default_arena;
-}
-
-static DefaultPagesAllocator *default_pages_allocator;
-static union {
- char chars[sizeof(DefaultPagesAllocator)];
- void *ptr;
-} debug_pages_allocator_space;
-
-LowLevelAlloc::PagesAllocator *LowLevelAlloc::GetDefaultPagesAllocator(void) {
- if (default_pages_allocator) {
- return default_pages_allocator;
- }
- default_pages_allocator = new (debug_pages_allocator_space.chars) DefaultPagesAllocator();
- return default_pages_allocator;
-}
-
-void *DefaultPagesAllocator::MapPages(int32 flags, size_t size) {
- void *new_pages;
- if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
- new_pages = MallocHook::UnhookedMMap(0, size,
- PROT_WRITE|PROT_READ,
- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- } else {
- new_pages = mmap(0, size,
- PROT_WRITE|PROT_READ,
- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- }
- RAW_CHECK(new_pages != MAP_FAILED, "mmap error");
-
- return new_pages;
-}
-
-void DefaultPagesAllocator::UnMapPages(int32 flags, void *region, size_t size) {
- int munmap_result;
- if ((flags & LowLevelAlloc::kAsyncSignalSafe) == 0) {
- munmap_result = munmap(region, size);
- } else {
- munmap_result = MallocHook::UnhookedMUnmap(region, size);
- }
- RAW_CHECK(munmap_result == 0,
- "LowLevelAlloc::DeleteArena: munmap failed address");
-}
diff --git a/src/third_party/gperftools-2.5/src/base/low_level_alloc.h b/src/third_party/gperftools-2.5/src/base/low_level_alloc.h
deleted file mode 100644
index d8dfc8f3929..00000000000
--- a/src/third_party/gperftools-2.5/src/base/low_level_alloc.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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.
- */
-
-#if !defined(_BASE_LOW_LEVEL_ALLOC_H_)
-#define _BASE_LOW_LEVEL_ALLOC_H_
-
-// A simple thread-safe memory allocator that does not depend on
-// mutexes or thread-specific data. It is intended to be used
-// sparingly, and only when malloc() would introduce an unwanted
-// dependency, such as inside the heap-checker.
-
-#include <config.h>
-#include <stddef.h> // for size_t
-#include "base/basictypes.h"
-
-class LowLevelAlloc {
- public:
- class PagesAllocator {
- public:
- virtual ~PagesAllocator();
- virtual void *MapPages(int32 flags, size_t size) = 0;
- virtual void UnMapPages(int32 flags, void *addr, size_t size) = 0;
- };
-
- static PagesAllocator *GetDefaultPagesAllocator(void);
-
- struct Arena; // an arena from which memory may be allocated
-
- // Returns a pointer to a block of at least "request" bytes
- // that have been newly allocated from the specific arena.
- // for Alloc() call the DefaultArena() is used.
- // Returns 0 if passed request==0.
- // Does not return 0 under other circumstances; it crashes if memory
- // is not available.
- static void *Alloc(size_t request)
- ATTRIBUTE_SECTION(malloc_hook);
- static void *AllocWithArena(size_t request, Arena *arena)
- ATTRIBUTE_SECTION(malloc_hook);
-
- // Deallocates a region of memory that was previously allocated with
- // Alloc(). Does nothing if passed 0. "s" must be either 0,
- // or must have been returned from a call to Alloc() and not yet passed to
- // Free() since that call to Alloc(). The space is returned to the arena
- // from which it was allocated.
- static void Free(void *s) ATTRIBUTE_SECTION(malloc_hook);
-
- // ATTRIBUTE_SECTION(malloc_hook) for Alloc* and Free
- // are to put all callers of MallocHook::Invoke* in this module
- // into special section,
- // so that MallocHook::GetCallerStackTrace can function accurately.
-
- // Create a new arena.
- // The root metadata for the new arena is allocated in the
- // meta_data_arena; the DefaultArena() can be passed for meta_data_arena.
- // These values may be ored into flags:
- enum {
- // Report calls to Alloc() and Free() via the MallocHook interface.
- // Set in the DefaultArena.
- kCallMallocHook = 0x0001,
-
- // Make calls to Alloc(), Free() be async-signal-safe. Not set in
- // DefaultArena().
- kAsyncSignalSafe = 0x0002,
-
- // When used with DefaultArena(), the NewArena() and DeleteArena() calls
- // obey the flags given explicitly in the NewArena() call, even if those
- // flags differ from the settings in DefaultArena(). So the call
- // NewArena(kAsyncSignalSafe, DefaultArena()) is itself async-signal-safe,
- // as well as generatating an arena that provides async-signal-safe
- // Alloc/Free.
- };
- static Arena *NewArena(int32 flags, Arena *meta_data_arena);
-
- // note: pages allocator will never be destroyed and allocated pages will never be freed
- // When allocator is NULL, it's same as NewArena
- static Arena *NewArenaWithCustomAlloc(int32 flags, Arena *meta_data_arena, PagesAllocator *allocator);
-
- // Destroys an arena allocated by NewArena and returns true,
- // provided no allocated blocks remain in the arena.
- // If allocated blocks remain in the arena, does nothing and
- // returns false.
- // It is illegal to attempt to destroy the DefaultArena().
- static bool DeleteArena(Arena *arena);
-
- // The default arena that always exists.
- static Arena *DefaultArena();
-
- private:
- LowLevelAlloc(); // no instances
-};
-
-#endif
diff --git a/src/third_party/gperftools-2.5/src/base/simple_mutex.h b/src/third_party/gperftools-2.5/src/base/simple_mutex.h
deleted file mode 100644
index a1886e46f31..00000000000
--- a/src/third_party/gperftools-2.5/src/base/simple_mutex.h
+++ /dev/null
@@ -1,332 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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.
-//
-// A simple mutex wrapper, supporting locks and read-write locks.
-// You should assume the locks are *not* re-entrant.
-//
-// To use: you should define the following macros in your configure.ac:
-// ACX_PTHREAD
-// AC_RWLOCK
-// The latter is defined in ../autoconf.
-//
-// This class is meant to be internal-only and should be wrapped by an
-// internal namespace. Before you use this module, please give the
-// name of your internal namespace for this module. Or, if you want
-// to expose it, you'll want to move it to the Google namespace. We
-// cannot put this class in global namespace because there can be some
-// problems when we have multiple versions of Mutex in each shared object.
-//
-// NOTE: TryLock() is broken for NO_THREADS mode, at least in NDEBUG
-// mode.
-//
-// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy:
-// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html
-// Because of that, we might as well use windows locks for
-// cygwin. They seem to be more reliable than the cygwin pthreads layer.
-//
-// TRICKY IMPLEMENTATION NOTE:
-// This class is designed to be safe to use during
-// dynamic-initialization -- that is, by global constructors that are
-// run before main() starts. The issue in this case is that
-// dynamic-initialization happens in an unpredictable order, and it
-// could be that someone else's dynamic initializer could call a
-// function that tries to acquire this mutex -- but that all happens
-// before this mutex's constructor has run. (This can happen even if
-// the mutex and the function that uses the mutex are in the same .cc
-// file.) Basically, because Mutex does non-trivial work in its
-// constructor, it's not, in the naive implementation, safe to use
-// before dynamic initialization has run on it.
-//
-// The solution used here is to pair the actual mutex primitive with a
-// bool that is set to true when the mutex is dynamically initialized.
-// (Before that it's false.) Then we modify all mutex routines to
-// look at the bool, and not try to lock/unlock until the bool makes
-// it to true (which happens after the Mutex constructor has run.)
-//
-// This works because before main() starts -- particularly, during
-// dynamic initialization -- there are no threads, so a) it's ok that
-// the mutex operations are a no-op, since we don't need locking then
-// anyway; and b) we can be quite confident our bool won't change
-// state between a call to Lock() and a call to Unlock() (that would
-// require a global constructor in one translation unit to call Lock()
-// and another global constructor in another translation unit to call
-// Unlock() later, which is pretty perverse).
-//
-// That said, it's tricky, and can conceivably fail; it's safest to
-// avoid trying to acquire a mutex in a global constructor, if you
-// can. One way it can fail is that a really smart compiler might
-// initialize the bool to true at static-initialization time (too
-// early) rather than at dynamic-initialization time. To discourage
-// that, we set is_safe_ to true in code (not the constructor
-// colon-initializer) and set it to true via a function that always
-// evaluates to true, but that the compiler can't know always
-// evaluates to true. This should be good enough.
-//
-// A related issue is code that could try to access the mutex
-// after it's been destroyed in the global destructors (because
-// the Mutex global destructor runs before some other global
-// destructor, that tries to acquire the mutex). The way we
-// deal with this is by taking a constructor arg that global
-// mutexes should pass in, that causes the destructor to do no
-// work. We still depend on the compiler not doing anything
-// weird to a Mutex's memory after it is destroyed, but for a
-// static global variable, that's pretty safe.
-
-#ifndef GOOGLE_MUTEX_H_
-#define GOOGLE_MUTEX_H_
-
-#include <config.h>
-
-#if defined(NO_THREADS)
- typedef int MutexType; // to keep a lock-count
-#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN // We only need minimal includes
-# endif
- // We need Windows NT or later for TryEnterCriticalSection(). If you
- // don't need that functionality, you can remove these _WIN32_WINNT
- // lines, and change TryLock() to assert(0) or something.
-# ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0400
-# endif
-# include <windows.h>
- typedef CRITICAL_SECTION MutexType;
-#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
- // Needed for pthread_rwlock_*. If it causes problems, you could take it
- // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
- // *does* cause problems for FreeBSD, or MacOSX, but isn't needed
- // for locking there.)
-# ifdef __linux__
-# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
-# endif
-# include <pthread.h>
- typedef pthread_rwlock_t MutexType;
-#elif defined(HAVE_PTHREAD)
-# include <pthread.h>
- typedef pthread_mutex_t MutexType;
-#else
-# error Need to implement mutex.h for your architecture, or #define NO_THREADS
-#endif
-
-#include <assert.h>
-#include <stdlib.h> // for abort()
-
-#define MUTEX_NAMESPACE perftools_mutex_namespace
-
-namespace MUTEX_NAMESPACE {
-
-class Mutex {
- public:
- // This is used for the single-arg constructor
- enum LinkerInitialized { LINKER_INITIALIZED };
-
- // Create a Mutex that is not held by anybody. This constructor is
- // typically used for Mutexes allocated on the heap or the stack.
- inline Mutex();
- // This constructor should be used for global, static Mutex objects.
- // It inhibits work being done by the destructor, which makes it
- // safer for code that tries to acqiure this mutex in their global
- // destructor.
- inline Mutex(LinkerInitialized);
-
- // Destructor
- inline ~Mutex();
-
- inline void Lock(); // Block if needed until free then acquire exclusively
- inline void Unlock(); // Release a lock acquired via Lock()
- inline bool TryLock(); // If free, Lock() and return true, else return false
- // Note that on systems that don't support read-write locks, these may
- // be implemented as synonyms to Lock() and Unlock(). So you can use
- // these for efficiency, but don't use them anyplace where being able
- // to do shared reads is necessary to avoid deadlock.
- inline void ReaderLock(); // Block until free or shared then acquire a share
- inline void ReaderUnlock(); // Release a read share of this Mutex
- inline void WriterLock() { Lock(); } // Acquire an exclusive lock
- inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
-
- private:
- MutexType mutex_;
- // We want to make sure that the compiler sets is_safe_ to true only
- // when we tell it to, and never makes assumptions is_safe_ is
- // always true. volatile is the most reliable way to do that.
- volatile bool is_safe_;
- // This indicates which constructor was called.
- bool destroy_;
-
- inline void SetIsSafe() { is_safe_ = true; }
-
- // Catch the error of writing Mutex when intending MutexLock.
- Mutex(Mutex* /*ignored*/) {}
- // Disallow "evil" constructors
- Mutex(const Mutex&);
- void operator=(const Mutex&);
-};
-
-// Now the implementation of Mutex for various systems
-#if defined(NO_THREADS)
-
-// When we don't have threads, we can be either reading or writing,
-// but not both. We can have lots of readers at once (in no-threads
-// mode, that's most likely to happen in recursive function calls),
-// but only one writer. We represent this by having mutex_ be -1 when
-// writing and a number > 0 when reading (and 0 when no lock is held).
-//
-// In debug mode, we assert these invariants, while in non-debug mode
-// we do nothing, for efficiency. That's why everything is in an
-// assert.
-
-Mutex::Mutex() : mutex_(0) { }
-Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { }
-Mutex::~Mutex() { assert(mutex_ == 0); }
-void Mutex::Lock() { assert(--mutex_ == -1); }
-void Mutex::Unlock() { assert(mutex_++ == -1); }
-bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
-void Mutex::ReaderLock() { assert(++mutex_ > 0); }
-void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
-
-#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
-
-Mutex::Mutex() : destroy_(true) {
- InitializeCriticalSection(&mutex_);
- SetIsSafe();
-}
-Mutex::Mutex(LinkerInitialized) : destroy_(false) {
- InitializeCriticalSection(&mutex_);
- SetIsSafe();
-}
-Mutex::~Mutex() { if (destroy_) DeleteCriticalSection(&mutex_); }
-void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
-void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
-bool Mutex::TryLock() { return is_safe_ ?
- TryEnterCriticalSection(&mutex_) != 0 : true; }
-void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
-void Mutex::ReaderUnlock() { Unlock(); }
-
-#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
-
-#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
- if (is_safe_ && fncall(&mutex_) != 0) abort(); \
-} while (0)
-
-Mutex::Mutex() : destroy_(true) {
- SetIsSafe();
- if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
-}
-Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
- SetIsSafe();
- if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
-}
-Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); }
-void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
-void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
-bool Mutex::TryLock() { return is_safe_ ?
- pthread_rwlock_trywrlock(&mutex_) == 0 : true; }
-void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
-void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
-#undef SAFE_PTHREAD
-
-#elif defined(HAVE_PTHREAD)
-
-#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
- if (is_safe_ && fncall(&mutex_) != 0) abort(); \
-} while (0)
-
-Mutex::Mutex() : destroy_(true) {
- SetIsSafe();
- if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
-}
-Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
- SetIsSafe();
- if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
-}
-Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); }
-void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
-void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
-bool Mutex::TryLock() { return is_safe_ ?
- pthread_mutex_trylock(&mutex_) == 0 : true; }
-void Mutex::ReaderLock() { Lock(); }
-void Mutex::ReaderUnlock() { Unlock(); }
-#undef SAFE_PTHREAD
-
-#endif
-
-// --------------------------------------------------------------------------
-// Some helper classes
-
-// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
-class MutexLock {
- public:
- explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
- ~MutexLock() { mu_->Unlock(); }
- private:
- Mutex * const mu_;
- // Disallow "evil" constructors
- MutexLock(const MutexLock&);
- void operator=(const MutexLock&);
-};
-
-// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
-class ReaderMutexLock {
- public:
- explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
- ~ReaderMutexLock() { mu_->ReaderUnlock(); }
- private:
- Mutex * const mu_;
- // Disallow "evil" constructors
- ReaderMutexLock(const ReaderMutexLock&);
- void operator=(const ReaderMutexLock&);
-};
-
-class WriterMutexLock {
- public:
- explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
- ~WriterMutexLock() { mu_->WriterUnlock(); }
- private:
- Mutex * const mu_;
- // Disallow "evil" constructors
- WriterMutexLock(const WriterMutexLock&);
- void operator=(const WriterMutexLock&);
-};
-
-// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
-#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
-#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
-#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
-
-} // namespace MUTEX_NAMESPACE
-
-using namespace MUTEX_NAMESPACE;
-
-#undef MUTEX_NAMESPACE
-
-#endif /* #define GOOGLE_SIMPLE_MUTEX_H_ */
diff --git a/src/third_party/gperftools-2.5/src/base/spinlock.cc b/src/third_party/gperftools-2.5/src/base/spinlock.cc
deleted file mode 100644
index acb01c8537a..00000000000
--- a/src/third_party/gperftools-2.5/src/base/spinlock.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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
- */
-
-#include <config.h>
-#include "base/spinlock.h"
-#include "base/spinlock_internal.h"
-#include "base/sysinfo.h" /* for GetSystemCPUsCount() */
-
-// NOTE on the Lock-state values:
-//
-// kSpinLockFree represents the unlocked state
-// kSpinLockHeld represents the locked state with no waiters
-// kSpinLockSleeper represents the locked state with waiters
-
-static int adaptive_spin_count = 0;
-
-const base::LinkerInitialized SpinLock::LINKER_INITIALIZED =
- base::LINKER_INITIALIZED;
-
-namespace {
-
-const int64_t kNanoPerSec = uint64_t(1000) * 1000 * 1000;
-
-#ifdef _WIN32
-int64_t frequency;
-
-void InitTimer() {
- LARGE_INTEGER large_freq;
- QueryPerformanceFrequency(&large_freq);
- frequency = large_freq.QuadPart;
-}
-
-int64_t NowMonotonic() {
- LARGE_INTEGER time_value;
- QueryPerformanceCounter(&time_value);
- return time_value.QuadPart;
-}
-
-int64_t TicksToNanos(int64_t timer_value) {
- return timer_value * kNanoPerSec / frequency;
-}
-
-#else // _WIN32
-void InitTimer() {}
-
-int64_t NowMonotonic() {
- struct timespec t;
-
- if (clock_gettime(CLOCK_MONOTONIC, &t)) {
- return 0;
- }
-
- return (static_cast<double>(t.tv_sec) * kNanoPerSec) + t.tv_nsec;
-}
-
-int64_t TicksToNanos(int64_t timer_value) {
- return timer_value;
-}
-
-#endif // _WIN32
-
-struct SpinLock_InitHelper {
- SpinLock_InitHelper() {
- // On multi-cpu machines, spin for longer before yielding
- // the processor or sleeping. Reduces idle time significantly.
- if (GetSystemCPUsCount() > 1) {
- adaptive_spin_count = 1000;
- }
-
- InitTimer();
- }
-};
-
-// Hook into global constructor execution:
-// We do not do adaptive spinning before that,
-// but nothing lock-intensive should be going on at that time.
-static SpinLock_InitHelper init_helper;
-
-inline void SpinlockPause(void) {
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
- __asm__ __volatile__("rep; nop" : : );
-#endif
-}
-
-// The current version of atomic_ops.h lacks base::subtle::Barrier_AtomicIncrement
-// so a CAS loop is used instead.
-void NoBarrier_AtomicAdd(volatile base::subtle::Atomic64* ptr,
- base::subtle::Atomic64 increment) {
- base::subtle::Atomic64 base_value = base::subtle::NoBarrier_Load(ptr);
- while (true) {
- base::subtle::Atomic64 new_value;
- base::subtle::NoBarrier_Store(&new_value, base::subtle::NoBarrier_Load(&base_value)
- + base::subtle::NoBarrier_Load(&increment));
-
- // Swap in the new incremented value.
- base::subtle::Atomic64 cas_result = base::subtle::Acquire_CompareAndSwap(
- ptr, base_value, new_value);
-
- // Check if the increment succeeded.
- if (cas_result == base_value) {
- return;
- }
-
- // If the increment failed, just use the previous value as the value to
- // add our increment to.
- base_value = cas_result;
- };
-}
-
-} // unnamed namespace
-
-// Monitor the lock to see if its value changes within some time
-// period (adaptive_spin_count loop iterations). The last value read
-// from the lock is returned from the method.
-Atomic32 SpinLock::SpinLoop() {
- int c = adaptive_spin_count;
- while (base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree && --c > 0) {
- SpinlockPause();
- }
- return base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
- kSpinLockSleeper);
-}
-
-base::subtle::Atomic64 SpinLock::totalDelayNanos_ = 0;
-
-void SpinLock::SlowLock() {
- Atomic32 lock_value = SpinLoop();
-
- int lock_wait_call_count = 0;
- int64_t start = 0;
- while (lock_value != kSpinLockFree) {
- // If the lock is currently held, but not marked as having a sleeper, mark
- // it as having a sleeper.
- if (lock_value == kSpinLockHeld) {
- // Here, just "mark" that the thread is going to sleep. Don't store the
- // lock wait time in the lock as that will cause the current lock
- // owner to think it experienced contention.
- lock_value = base::subtle::Acquire_CompareAndSwap(&lockword_,
- kSpinLockHeld,
- kSpinLockSleeper);
- if (lock_value == kSpinLockHeld) {
- // Successfully transitioned to kSpinLockSleeper. Pass
- // kSpinLockSleeper to the SpinLockDelay routine to properly indicate
- // the last lock_value observed.
- lock_value = kSpinLockSleeper;
- } else if (lock_value == kSpinLockFree) {
- // Lock is free again, so try and acquire it before sleeping. The
- // new lock state will be the number of cycles this thread waited if
- // this thread obtains the lock.
- lock_value = base::subtle::Acquire_CompareAndSwap(&lockword_,
- kSpinLockFree,
- kSpinLockSleeper);
- continue; // skip the delay at the end of the loop
- }
- }
-
- // Wait for an OS specific delay.
- start = NowMonotonic();
- base::internal::SpinLockDelay(&lockword_, lock_value,
- ++lock_wait_call_count);
- // Spin again after returning from the wait routine to give this thread
- // some chance of obtaining the lock.
- lock_value = SpinLoop();
- }
-
- if (start) {
- NoBarrier_AtomicAdd(&totalDelayNanos_, static_cast<base::subtle::Atomic64>(
- TicksToNanos(NowMonotonic() - start)));
- }
-}
-
-void SpinLock::SlowUnlock() {
- // wake waiter if necessary
- base::internal::SpinLockWake(&lockword_, false);
-}
diff --git a/src/third_party/gperftools-2.5/src/base/spinlock.h b/src/third_party/gperftools-2.5/src/base/spinlock.h
deleted file mode 100644
index c5ad8f048f6..00000000000
--- a/src/third_party/gperftools-2.5/src/base/spinlock.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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
- */
-
-// SpinLock is async signal safe.
-// If used within a signal handler, all lock holders
-// should block the signal even outside the signal handler.
-
-#ifndef BASE_SPINLOCK_H_
-#define BASE_SPINLOCK_H_
-
-#include <config.h>
-#include "base/atomicops.h"
-#include "base/basictypes.h"
-#include "base/dynamic_annotations.h"
-#include "base/thread_annotations.h"
-
-class LOCKABLE SpinLock {
- public:
- SpinLock() : lockword_(kSpinLockFree) { }
-
- // Special constructor for use with static SpinLock objects. E.g.,
- //
- // static SpinLock lock(base::LINKER_INITIALIZED);
- //
- // When intialized using this constructor, we depend on the fact
- // that the linker has already initialized the memory appropriately.
- // A SpinLock constructed like this can be freely used from global
- // initializers without worrying about the order in which global
- // initializers run.
- explicit SpinLock(base::LinkerInitialized /*x*/) {
- // Does nothing; lockword_ is already initialized
- }
-
- // Acquire this SpinLock.
- // TODO(csilvers): uncomment the annotation when we figure out how to
- // support this macro with 0 args (see thread_annotations.h)
- inline void Lock() /*EXCLUSIVE_LOCK_FUNCTION()*/ {
- if (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
- kSpinLockHeld) != kSpinLockFree) {
- SlowLock();
- }
- ANNOTATE_RWLOCK_ACQUIRED(this, 1);
- }
-
- // Try to acquire this SpinLock without blocking and return true if the
- // acquisition was successful. If the lock was not acquired, false is
- // returned. If this SpinLock is free at the time of the call, TryLock
- // will return true with high probability.
- inline bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
- bool res =
- (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
- kSpinLockHeld) == kSpinLockFree);
- if (res) {
- ANNOTATE_RWLOCK_ACQUIRED(this, 1);
- }
- return res;
- }
-
- // Release this SpinLock, which must be held by the calling thread.
- // TODO(csilvers): uncomment the annotation when we figure out how to
- // support this macro with 0 args (see thread_annotations.h)
- inline void Unlock() /*UNLOCK_FUNCTION()*/ {
- ANNOTATE_RWLOCK_RELEASED(this, 1);
- uint64 prev_value = static_cast<uint64>(
- base::subtle::Release_AtomicExchange(&lockword_, kSpinLockFree));
- if (prev_value != kSpinLockHeld) {
- // Speed the wakeup of any waiter.
- SlowUnlock();
- }
- }
-
- // Determine if the lock is held. When the lock is held by the invoking
- // thread, true will always be returned. Intended to be used as
- // CHECK(lock.IsHeld()).
- inline bool IsHeld() const {
- return base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree;
- }
-
- static base::subtle::Atomic64 GetTotalDelayNanos() {
- return base::subtle::NoBarrier_Load(&totalDelayNanos_);
- }
-
- static const base::LinkerInitialized LINKER_INITIALIZED; // backwards compat
- private:
- enum { kSpinLockFree = 0 };
- enum { kSpinLockHeld = 1 };
- enum { kSpinLockSleeper = 2 };
-
- volatile Atomic32 lockword_;
-
- static base::subtle::Atomic64 totalDelayNanos_;
-
- void SlowLock();
- void SlowUnlock();
- Atomic32 SpinLoop();
-
- DISALLOW_COPY_AND_ASSIGN(SpinLock);
-};
-
-// Corresponding locker object that arranges to acquire a spinlock for
-// the duration of a C++ scope.
-class SCOPED_LOCKABLE SpinLockHolder {
- private:
- SpinLock* lock_;
- public:
- inline explicit SpinLockHolder(SpinLock* l) EXCLUSIVE_LOCK_FUNCTION(l)
- : lock_(l) {
- l->Lock();
- }
- // TODO(csilvers): uncomment the annotation when we figure out how to
- // support this macro with 0 args (see thread_annotations.h)
- inline ~SpinLockHolder() /*UNLOCK_FUNCTION()*/ { lock_->Unlock(); }
-};
-// Catch bug where variable name is omitted, e.g. SpinLockHolder (&lock);
-#define SpinLockHolder(x) COMPILE_ASSERT(0, spin_lock_decl_missing_var_name)
-
-
-#endif // BASE_SPINLOCK_H_
diff --git a/src/third_party/gperftools-2.5/src/base/spinlock_internal.cc b/src/third_party/gperftools-2.5/src/base/spinlock_internal.cc
deleted file mode 100644
index d9629717be1..00000000000
--- a/src/third_party/gperftools-2.5/src/base/spinlock_internal.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2010, 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.
- */
-
-// The OS-specific header included below must provide two calls:
-// base::internal::SpinLockDelay() and base::internal::SpinLockWake().
-// See spinlock_internal.h for the spec of SpinLockWake().
-
-// void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop)
-// SpinLockDelay() generates an apprproate spin delay on iteration "loop" of a
-// spin loop on location *w, whose previously observed value was "value".
-// SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick,
-// or may wait for a delay that can be truncated by a call to SpinlockWake(w).
-// In all cases, it must return in bounded time even if SpinlockWake() is not
-// called.
-
-#include "base/spinlock_internal.h"
-
-// forward declaration for use by spinlock_*-inl.h
-namespace base { namespace internal { static int SuggestedDelayNS(int loop); }}
-
-#if defined(_WIN32)
-#include "base/spinlock_win32-inl.h"
-#elif defined(__linux__)
-#include "base/spinlock_linux-inl.h"
-#else
-#include "base/spinlock_posix-inl.h"
-#endif
-
-namespace base {
-namespace internal {
-
-// Return a suggested delay in nanoseconds for iteration number "loop"
-static int SuggestedDelayNS(int loop) {
- // Weak pseudo-random number generator to get some spread between threads
- // when many are spinning.
-#ifdef BASE_HAS_ATOMIC64
- static base::subtle::Atomic64 rand;
- uint64 r = base::subtle::NoBarrier_Load(&rand);
- r = 0x5deece66dLL * r + 0xb; // numbers from nrand48()
- base::subtle::NoBarrier_Store(&rand, r);
-
- r <<= 16; // 48-bit random number now in top 48-bits.
- if (loop < 0 || loop > 32) { // limit loop to 0..32
- loop = 32;
- }
- // loop>>3 cannot exceed 4 because loop cannot exceed 32.
- // Select top 20..24 bits of lower 48 bits,
- // giving approximately 0ms to 16ms.
- // Mean is exponential in loop for first 32 iterations, then 8ms.
- // The futex path multiplies this by 16, since we expect explicit wakeups
- // almost always on that path.
- return r >> (44 - (loop >> 3));
-#else
- static Atomic32 rand;
- uint32 r = base::subtle::NoBarrier_Load(&rand);
- r = 0x343fd * r + 0x269ec3; // numbers from MSVC++
- base::subtle::NoBarrier_Store(&rand, r);
-
- r <<= 1; // 31-bit random number now in top 31-bits.
- if (loop < 0 || loop > 32) { // limit loop to 0..32
- loop = 32;
- }
- // loop>>3 cannot exceed 4 because loop cannot exceed 32.
- // Select top 20..24 bits of lower 31 bits,
- // giving approximately 0ms to 16ms.
- // Mean is exponential in loop for first 32 iterations, then 8ms.
- // The futex path multiplies this by 16, since we expect explicit wakeups
- // almost always on that path.
- return r >> (12 - (loop >> 3));
-#endif
-}
-
-} // namespace internal
-} // namespace base
diff --git a/src/third_party/gperftools-2.5/src/base/spinlock_internal.h b/src/third_party/gperftools-2.5/src/base/spinlock_internal.h
deleted file mode 100644
index aa47e67d4e0..00000000000
--- a/src/third_party/gperftools-2.5/src/base/spinlock_internal.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2010, 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.
- *
- * ---
- * This file is an internal part spinlock.cc and once.cc
- * It may not be used directly by code outside of //base.
- */
-
-#ifndef BASE_SPINLOCK_INTERNAL_H_
-#define BASE_SPINLOCK_INTERNAL_H_
-
-#include <config.h>
-#include "base/basictypes.h"
-#include "base/atomicops.h"
-
-namespace base {
-namespace internal {
-
-void SpinLockWake(volatile Atomic32 *w, bool all);
-void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop);
-
-} // namespace internal
-} // namespace base
-#endif
diff --git a/src/third_party/gperftools-2.5/src/base/spinlock_linux-inl.h b/src/third_party/gperftools-2.5/src/base/spinlock_linux-inl.h
deleted file mode 100644
index aadf62a4b67..00000000000
--- a/src/third_party/gperftools-2.5/src/base/spinlock_linux-inl.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2009, 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.
- *
- * ---
- * This file is a Linux-specific part of spinlock_internal.cc
- */
-
-#include <errno.h>
-#include <sched.h>
-#include <time.h>
-#include <limits.h>
-#include "base/linux_syscall_support.h"
-
-#define FUTEX_WAIT 0
-#define FUTEX_WAKE 1
-#define FUTEX_PRIVATE_FLAG 128
-
-static bool have_futex;
-static int futex_private_flag = FUTEX_PRIVATE_FLAG;
-
-namespace {
-static struct InitModule {
- InitModule() {
- int x = 0;
- // futexes are ints, so we can use them only when
- // that's the same size as the lockword_ in SpinLock.
- have_futex = (sizeof (Atomic32) == sizeof (int) &&
- sys_futex(&x, FUTEX_WAKE, 1, NULL, NULL, 0) >= 0);
- if (have_futex &&
- sys_futex(&x, FUTEX_WAKE | futex_private_flag, 1, NULL, NULL, 0) < 0) {
- futex_private_flag = 0;
- }
- }
-} init_module;
-
-} // anonymous namespace
-
-
-namespace base {
-namespace internal {
-
-void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) {
- if (loop != 0) {
- int save_errno = errno;
- struct timespec tm;
- tm.tv_sec = 0;
- if (have_futex) {
- tm.tv_nsec = base::internal::SuggestedDelayNS(loop);
- } else {
- tm.tv_nsec = 2000001; // above 2ms so linux 2.4 doesn't spin
- }
- if (have_futex) {
- tm.tv_nsec *= 16; // increase the delay; we expect explicit wakeups
- sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
- FUTEX_WAIT | futex_private_flag,
- value, reinterpret_cast<struct kernel_timespec *>(&tm),
- NULL, 0);
- } else {
- nanosleep(&tm, NULL);
- }
- errno = save_errno;
- }
-}
-
-void SpinLockWake(volatile Atomic32 *w, bool all) {
- if (have_futex) {
- sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
- FUTEX_WAKE | futex_private_flag, all? INT_MAX : 1,
- NULL, NULL, 0);
- }
-}
-
-} // namespace internal
-} // namespace base
diff --git a/src/third_party/gperftools-2.5/src/base/spinlock_posix-inl.h b/src/third_party/gperftools-2.5/src/base/spinlock_posix-inl.h
deleted file mode 100644
index e73a30fb7d8..00000000000
--- a/src/third_party/gperftools-2.5/src/base/spinlock_posix-inl.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2009, 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.
- *
- * ---
- * This file is a Posix-specific part of spinlock_internal.cc
- */
-
-#include <config.h>
-#include <errno.h>
-#ifdef HAVE_SCHED_H
-#include <sched.h> /* For sched_yield() */
-#endif
-#include <time.h> /* For nanosleep() */
-
-namespace base {
-namespace internal {
-
-void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) {
- int save_errno = errno;
- if (loop == 0) {
- } else if (loop == 1) {
- sched_yield();
- } else {
- struct timespec tm;
- tm.tv_sec = 0;
- tm.tv_nsec = base::internal::SuggestedDelayNS(loop);
- nanosleep(&tm, NULL);
- }
- errno = save_errno;
-}
-
-void SpinLockWake(volatile Atomic32 *w, bool all) {
-}
-
-} // namespace internal
-} // namespace base
diff --git a/src/third_party/gperftools-2.5/src/base/spinlock_win32-inl.h b/src/third_party/gperftools-2.5/src/base/spinlock_win32-inl.h
deleted file mode 100644
index 956b9653e6d..00000000000
--- a/src/third_party/gperftools-2.5/src/base/spinlock_win32-inl.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2009, 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.
- *
- * ---
- * This file is a Win32-specific part of spinlock_internal.cc
- */
-
-
-#include <windows.h>
-
-namespace base {
-namespace internal {
-
-void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) {
- if (loop == 0) {
- } else if (loop == 1) {
- Sleep(0);
- } else {
- Sleep(base::internal::SuggestedDelayNS(loop) / 1000000);
- }
-}
-
-void SpinLockWake(volatile Atomic32 *w, bool all) {
-}
-
-} // namespace internal
-} // namespace base
diff --git a/src/third_party/gperftools-2.5/src/base/stl_allocator.h b/src/third_party/gperftools-2.5/src/base/stl_allocator.h
deleted file mode 100644
index 2345f463c24..00000000000
--- a/src/third_party/gperftools-2.5/src/base/stl_allocator.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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: Maxim Lifantsev
- */
-
-
-#ifndef BASE_STL_ALLOCATOR_H_
-#define BASE_STL_ALLOCATOR_H_
-
-#include <config.h>
-
-#include <stddef.h> // for ptrdiff_t
-#include <limits>
-
-#include "base/logging.h"
-
-// Generic allocator class for STL objects
-// that uses a given type-less allocator Alloc, which must provide:
-// static void* Alloc::Allocate(size_t size);
-// static void Alloc::Free(void* ptr, size_t size);
-//
-// STL_Allocator<T, MyAlloc> provides the same thread-safety
-// guarantees as MyAlloc.
-//
-// Usage example:
-// set<T, less<T>, STL_Allocator<T, MyAlloc> > my_set;
-// CAVEAT: Parts of the code below are probably specific
-// to the STL version(s) we are using.
-// The code is simply lifted from what std::allocator<> provides.
-template <typename T, class Alloc>
-class STL_Allocator {
- public:
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T value_type;
-
- template <class T1> struct rebind {
- typedef STL_Allocator<T1, Alloc> other;
- };
-
- STL_Allocator() { }
- STL_Allocator(const STL_Allocator&) { }
- template <class T1> STL_Allocator(const STL_Allocator<T1, Alloc>&) { }
- ~STL_Allocator() { }
-
- pointer address(reference x) const { return &x; }
- const_pointer address(const_reference x) const { return &x; }
-
- pointer allocate(size_type n, const void* = 0) {
- RAW_DCHECK((n * sizeof(T)) / sizeof(T) == n, "n is too big to allocate");
- return static_cast<T*>(Alloc::Allocate(n * sizeof(T)));
- }
- void deallocate(pointer p, size_type n) { Alloc::Free(p, n * sizeof(T)); }
-
- size_type max_size() const { return size_t(-1) / sizeof(T); }
-
- void construct(pointer p, const T& val) { ::new(p) T(val); }
- void construct(pointer p) { ::new(p) T(); }
- void destroy(pointer p) { p->~T(); }
-
- // There's no state, so these allocators are always equal
- bool operator==(const STL_Allocator&) const { return true; }
-};
-
-#endif // BASE_STL_ALLOCATOR_H_
diff --git a/src/third_party/gperftools-2.5/src/base/sysinfo.cc b/src/third_party/gperftools-2.5/src/base/sysinfo.cc
deleted file mode 100644
index 789a47d2977..00000000000
--- a/src/third_party/gperftools-2.5/src/base/sysinfo.cc
+++ /dev/null
@@ -1,860 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2006, 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.
-
-#include <config.h>
-#if (defined(_WIN32) || defined(__MINGW32__)) && !defined(__CYGWIN__) && !defined(__CYGWIN32)
-# define PLATFORM_WINDOWS 1
-#endif
-
-#include <ctype.h> // for isspace()
-#include <stdlib.h> // for getenv()
-#include <stdio.h> // for snprintf(), sscanf()
-#include <string.h> // for memmove(), memchr(), etc.
-#include <fcntl.h> // for open()
-#include <errno.h> // for errno
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for read()
-#endif
-#if defined __MACH__ // Mac OS X, almost certainly
-#include <mach-o/dyld.h> // for iterating over dll's in ProcMapsIter
-#include <mach-o/loader.h> // for iterating over dll's in ProcMapsIter
-#include <sys/types.h>
-#include <sys/sysctl.h> // how we figure out numcpu's on OS X
-#elif defined __FreeBSD__
-#include <sys/sysctl.h>
-#elif defined __sun__ // Solaris
-#include <procfs.h> // for, e.g., prmap_t
-#elif defined(PLATFORM_WINDOWS)
-#include <process.h> // for getpid() (actually, _getpid())
-#include <shlwapi.h> // for SHGetValueA()
-#include <tlhelp32.h> // for Module32First()
-#endif
-#include "base/sysinfo.h"
-#include "base/commandlineflags.h"
-#include "base/dynamic_annotations.h" // for RunningOnValgrind
-#include "base/logging.h"
-
-#ifdef PLATFORM_WINDOWS
-#ifdef MODULEENTRY32
-// In a change from the usual W-A pattern, there is no A variant of
-// MODULEENTRY32. Tlhelp32.h #defines the W variant, but not the A.
-// In unicode mode, tlhelp32.h #defines MODULEENTRY32 to be
-// MODULEENTRY32W. These #undefs are the only way I see to get back
-// access to the original, ascii struct (and related functions).
-#undef MODULEENTRY32
-#undef Module32First
-#undef Module32Next
-#undef PMODULEENTRY32
-#undef LPMODULEENTRY32
-#endif /* MODULEENTRY32 */
-// MinGW doesn't seem to define this, perhaps some windowsen don't either.
-#ifndef TH32CS_SNAPMODULE32
-#define TH32CS_SNAPMODULE32 0
-#endif /* TH32CS_SNAPMODULE32 */
-#endif /* PLATFORM_WINDOWS */
-
-// Re-run fn until it doesn't cause EINTR.
-#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR)
-
-// open/read/close can set errno, which may be illegal at this
-// time, so prefer making the syscalls directly if we can.
-#ifdef HAVE_SYS_SYSCALL_H
-# include <sys/syscall.h>
-#endif
-#ifdef SYS_open // solaris 11, at least sometimes, only defines SYS_openat
-# define safeopen(filename, mode) syscall(SYS_open, filename, mode)
-#else
-# define safeopen(filename, mode) open(filename, mode)
-#endif
-#ifdef SYS_read
-# define saferead(fd, buffer, size) syscall(SYS_read, fd, buffer, size)
-#else
-# define saferead(fd, buffer, size) read(fd, buffer, size)
-#endif
-#ifdef SYS_close
-# define safeclose(fd) syscall(SYS_close, fd)
-#else
-# define safeclose(fd) close(fd)
-#endif
-
-// ----------------------------------------------------------------------
-// GetenvBeforeMain()
-// GetUniquePathFromEnv()
-// Some non-trivial getenv-related functions.
-// ----------------------------------------------------------------------
-
-// It's not safe to call getenv() in the malloc hooks, because they
-// might be called extremely early, before libc is done setting up
-// correctly. In particular, the thread library may not be done
-// setting up errno. So instead, we use the built-in __environ array
-// if it exists, and otherwise read /proc/self/environ directly, using
-// system calls to read the file, and thus avoid setting errno.
-// /proc/self/environ has a limit of how much data it exports (around
-// 8K), so it's not an ideal solution.
-const char* GetenvBeforeMain(const char* name) {
-#if defined(HAVE___ENVIRON) // if we have it, it's declared in unistd.h
- if (__environ) { // can exist but be NULL, if statically linked
- const int namelen = strlen(name);
- for (char** p = __environ; *p; p++) {
- if (strlen(*p) < namelen) {
- continue;
- }
- if (!memcmp(*p, name, namelen) && (*p)[namelen] == '=') // it's a match
- return *p + namelen+1; // point after =
- }
- return NULL;
- }
-#endif
-#if defined(PLATFORM_WINDOWS)
- // TODO(mbelshe) - repeated calls to this function will overwrite the
- // contents of the static buffer.
- static char envvar_buf[1024]; // enough to hold any envvar we care about
- if (!GetEnvironmentVariableA(name, envvar_buf, sizeof(envvar_buf)-1))
- return NULL;
- return envvar_buf;
-#endif
- // static is ok because this function should only be called before
- // main(), when we're single-threaded.
- static char envbuf[16<<10];
- if (*envbuf == '\0') { // haven't read the environ yet
- int fd = safeopen("/proc/self/environ", O_RDONLY);
- // The -2 below guarantees the last two bytes of the buffer will be \0\0
- if (fd == -1 || // unable to open the file, fall back onto libc
- saferead(fd, envbuf, sizeof(envbuf) - 2) < 0) { // error reading file
- RAW_VLOG(1, "Unable to open /proc/self/environ, falling back "
- "on getenv(\"%s\"), which may not work", name);
- if (fd != -1) safeclose(fd);
- return getenv(name);
- }
- safeclose(fd);
- }
- const int namelen = strlen(name);
- const char* p = envbuf;
- while (*p != '\0') { // will happen at the \0\0 that terminates the buffer
- // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
- const char* endp = (char*)memchr(p, '\0', sizeof(envbuf) - (p - envbuf));
- if (endp == NULL) // this entry isn't NUL terminated
- return NULL;
- else if (!memcmp(p, name, namelen) && p[namelen] == '=') // it's a match
- return p + namelen+1; // point after =
- p = endp + 1;
- }
- return NULL; // env var never found
-}
-
-extern "C" {
- const char* TCMallocGetenvSafe(const char* name) {
- return GetenvBeforeMain(name);
- }
-}
-
-// This takes as an argument an environment-variable name (like
-// CPUPROFILE) whose value is supposed to be a file-path, and sets
-// path to that path, and returns true. If the env var doesn't exist,
-// or is the empty string, leave path unchanged and returns false.
-// The reason this is non-trivial is that this function handles munged
-// pathnames. Here's why:
-//
-// If we're a child process of the 'main' process, we can't just use
-// getenv("CPUPROFILE") -- the parent process will be using that path.
-// Instead we append our pid to the pathname. How do we tell if we're a
-// child process? Ideally we'd set an environment variable that all
-// our children would inherit. But -- and this is seemingly a bug in
-// gcc -- if you do a setenv() in a shared libarary in a global
-// constructor, the environment setting is lost by the time main() is
-// called. The only safe thing we can do in such a situation is to
-// modify the existing envvar. So we do a hack: in the parent, we set
-// the high bit of the 1st char of CPUPROFILE. In the child, we
-// notice the high bit is set and append the pid(). This works
-// assuming cpuprofile filenames don't normally have the high bit set
-// in their first character! If that assumption is violated, we'll
-// still get a profile, but one with an unexpected name.
-// TODO(csilvers): set an envvar instead when we can do it reliably.
-bool GetUniquePathFromEnv(const char* env_name, char* path) {
- char* envval = getenv(env_name);
- if (envval == NULL || *envval == '\0')
- return false;
- if (envval[0] & 128) { // high bit is set
- snprintf(path, PATH_MAX, "%c%s_%u", // add pid and clear high bit
- envval[0] & 127, envval+1, (unsigned int)(getpid()));
- } else {
- snprintf(path, PATH_MAX, "%s", envval);
- envval[0] |= 128; // set high bit for kids to see
- }
- return true;
-}
-
-void SleepForMilliseconds(int milliseconds) {
-#ifdef PLATFORM_WINDOWS
- _sleep(milliseconds); // Windows's _sleep takes milliseconds argument
-#else
- // Sleep for a few milliseconds
- struct timespec sleep_time;
- sleep_time.tv_sec = milliseconds / 1000;
- sleep_time.tv_nsec = (milliseconds % 1000) * 1000000;
- while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR)
- ; // Ignore signals and wait for the full interval to elapse.
-#endif
-}
-
-int GetSystemCPUsCount()
-{
-#if defined(PLATFORM_WINDOWS)
- // Get the number of processors.
- SYSTEM_INFO info;
- GetSystemInfo(&info);
- return info.dwNumberOfProcessors;
-#else
- long rv = sysconf(_SC_NPROCESSORS_ONLN);
- if (rv < 0) {
- return 1;
- }
- return static_cast<int>(rv);
-#endif
-}
-
-// ----------------------------------------------------------------------
-
-#if defined __linux__ || defined __FreeBSD__ || defined __sun__ || defined __CYGWIN__ || defined __CYGWIN32__
-static void ConstructFilename(const char* spec, pid_t pid,
- char* buf, int buf_size) {
- CHECK_LT(snprintf(buf, buf_size,
- spec,
- static_cast<int>(pid ? pid : getpid())), buf_size);
-}
-#endif
-
-// A templatized helper function instantiated for Mach (OS X) only.
-// It can handle finding info for both 32 bits and 64 bits.
-// Returns true if it successfully handled the hdr, false else.
-#ifdef __MACH__ // Mac OS X, almost certainly
-template<uint32_t kMagic, uint32_t kLCSegment,
- typename MachHeader, typename SegmentCommand>
-static bool NextExtMachHelper(const mach_header* hdr,
- int current_image, int current_load_cmd,
- uint64 *start, uint64 *end, char **flags,
- uint64 *offset, int64 *inode, char **filename,
- uint64 *file_mapping, uint64 *file_pages,
- uint64 *anon_mapping, uint64 *anon_pages,
- dev_t *dev) {
- static char kDefaultPerms[5] = "r-xp";
- if (hdr->magic != kMagic)
- return false;
- const char* lc = (const char *)hdr + sizeof(MachHeader);
- // TODO(csilvers): make this not-quadradic (increment and hold state)
- for (int j = 0; j < current_load_cmd; j++) // advance to *our* load_cmd
- lc += ((const load_command *)lc)->cmdsize;
- if (((const load_command *)lc)->cmd == kLCSegment) {
- const intptr_t dlloff = _dyld_get_image_vmaddr_slide(current_image);
- const SegmentCommand* sc = (const SegmentCommand *)lc;
- if (start) *start = sc->vmaddr + dlloff;
- if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
- if (flags) *flags = kDefaultPerms; // can we do better?
- if (offset) *offset = sc->fileoff;
- if (inode) *inode = 0;
- if (filename)
- *filename = const_cast<char*>(_dyld_get_image_name(current_image));
- if (file_mapping) *file_mapping = 0;
- if (file_pages) *file_pages = 0; // could we use sc->filesize?
- if (anon_mapping) *anon_mapping = 0;
- if (anon_pages) *anon_pages = 0;
- if (dev) *dev = 0;
- return true;
- }
-
- return false;
-}
-#endif
-
-// Finds |c| in |text|, and assign '\0' at the found position.
-// The original character at the modified position should be |c|.
-// A pointer to the modified position is stored in |endptr|.
-// |endptr| should not be NULL.
-static bool ExtractUntilChar(char *text, int c, char **endptr) {
- CHECK_NE(text, NULL);
- CHECK_NE(endptr, NULL);
- char *found;
- found = strchr(text, c);
- if (found == NULL) {
- *endptr = NULL;
- return false;
- }
-
- *endptr = found;
- *found = '\0';
- return true;
-}
-
-// Increments |*text_pointer| while it points a whitespace character.
-// It is to follow sscanf's whilespace handling.
-static void SkipWhileWhitespace(char **text_pointer, int c) {
- if (isspace(c)) {
- while (isspace(**text_pointer) && isspace(*((*text_pointer) + 1))) {
- ++(*text_pointer);
- }
- }
-}
-
-template<class T>
-static T StringToInteger(char *text, char **endptr, int base) {
- assert(false);
- return T();
-}
-
-template<>
-int StringToInteger<int>(char *text, char **endptr, int base) {
- return strtol(text, endptr, base);
-}
-
-template<>
-int64 StringToInteger<int64>(char *text, char **endptr, int base) {
- return strtoll(text, endptr, base);
-}
-
-template<>
-uint64 StringToInteger<uint64>(char *text, char **endptr, int base) {
- return strtoull(text, endptr, base);
-}
-
-template<typename T>
-static T StringToIntegerUntilChar(
- char *text, int base, int c, char **endptr_result) {
- CHECK_NE(endptr_result, NULL);
- *endptr_result = NULL;
-
- char *endptr_extract;
- if (!ExtractUntilChar(text, c, &endptr_extract))
- return 0;
-
- T result;
- char *endptr_strto;
- result = StringToInteger<T>(text, &endptr_strto, base);
- *endptr_extract = c;
-
- if (endptr_extract != endptr_strto)
- return 0;
-
- *endptr_result = endptr_extract;
- SkipWhileWhitespace(endptr_result, c);
-
- return result;
-}
-
-static char *CopyStringUntilChar(
- char *text, unsigned out_len, int c, char *out) {
- char *endptr;
- if (!ExtractUntilChar(text, c, &endptr))
- return NULL;
-
- strncpy(out, text, out_len);
- out[out_len-1] = '\0';
- *endptr = c;
-
- SkipWhileWhitespace(&endptr, c);
- return endptr;
-}
-
-template<typename T>
-static bool StringToIntegerUntilCharWithCheck(
- T *outptr, char *text, int base, int c, char **endptr) {
- *outptr = StringToIntegerUntilChar<T>(*endptr, base, c, endptr);
- if (*endptr == NULL || **endptr == '\0') return false;
- ++(*endptr);
- return true;
-}
-
-static bool ParseProcMapsLine(char *text, uint64 *start, uint64 *end,
- char *flags, uint64 *offset,
- int *major, int *minor, int64 *inode,
- unsigned *filename_offset) {
-#if defined(__linux__)
- /*
- * It's similar to:
- * sscanf(text, "%"SCNx64"-%"SCNx64" %4s %"SCNx64" %x:%x %"SCNd64" %n",
- * start, end, flags, offset, major, minor, inode, filename_offset)
- */
- char *endptr = text;
- if (endptr == NULL || *endptr == '\0') return false;
-
- if (!StringToIntegerUntilCharWithCheck(start, endptr, 16, '-', &endptr))
- return false;
-
- if (!StringToIntegerUntilCharWithCheck(end, endptr, 16, ' ', &endptr))
- return false;
-
- endptr = CopyStringUntilChar(endptr, 5, ' ', flags);
- if (endptr == NULL || *endptr == '\0') return false;
- ++endptr;
-
- if (!StringToIntegerUntilCharWithCheck(offset, endptr, 16, ' ', &endptr))
- return false;
-
- if (!StringToIntegerUntilCharWithCheck(major, endptr, 16, ':', &endptr))
- return false;
-
- if (!StringToIntegerUntilCharWithCheck(minor, endptr, 16, ' ', &endptr))
- return false;
-
- if (!StringToIntegerUntilCharWithCheck(inode, endptr, 10, ' ', &endptr))
- return false;
-
- *filename_offset = (endptr - text);
- return true;
-#else
- return false;
-#endif
-}
-
-ProcMapsIterator::ProcMapsIterator(pid_t pid) {
- Init(pid, NULL, false);
-}
-
-ProcMapsIterator::ProcMapsIterator(pid_t pid, Buffer *buffer) {
- Init(pid, buffer, false);
-}
-
-ProcMapsIterator::ProcMapsIterator(pid_t pid, Buffer *buffer,
- bool use_maps_backing) {
- Init(pid, buffer, use_maps_backing);
-}
-
-void ProcMapsIterator::Init(pid_t pid, Buffer *buffer,
- bool use_maps_backing) {
- pid_ = pid;
- using_maps_backing_ = use_maps_backing;
- dynamic_buffer_ = NULL;
- if (!buffer) {
- // If the user didn't pass in any buffer storage, allocate it
- // now. This is the normal case; the signal handler passes in a
- // static buffer.
- buffer = dynamic_buffer_ = new Buffer;
- } else {
- dynamic_buffer_ = NULL;
- }
-
- ibuf_ = buffer->buf_;
-
- stext_ = etext_ = nextline_ = ibuf_;
- ebuf_ = ibuf_ + Buffer::kBufSize - 1;
- nextline_ = ibuf_;
-
-#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
- if (use_maps_backing) { // don't bother with clever "self" stuff in this case
- ConstructFilename("/proc/%d/maps_backing", pid, ibuf_, Buffer::kBufSize);
- } else if (pid == 0) {
- // We have to kludge a bit to deal with the args ConstructFilename
- // expects. The 1 is never used -- it's only impt. that it's not 0.
- ConstructFilename("/proc/self/maps", 1, ibuf_, Buffer::kBufSize);
- } else {
- ConstructFilename("/proc/%d/maps", pid, ibuf_, Buffer::kBufSize);
- }
- // No error logging since this can be called from the crash dump
- // handler at awkward moments. Users should call Valid() before
- // using.
- NO_INTR(fd_ = open(ibuf_, O_RDONLY));
-#elif defined(__FreeBSD__)
- // We don't support maps_backing on freebsd
- if (pid == 0) {
- ConstructFilename("/proc/curproc/map", 1, ibuf_, Buffer::kBufSize);
- } else {
- ConstructFilename("/proc/%d/map", pid, ibuf_, Buffer::kBufSize);
- }
- NO_INTR(fd_ = open(ibuf_, O_RDONLY));
-#elif defined(__sun__)
- if (pid == 0) {
- ConstructFilename("/proc/self/map", 1, ibuf_, Buffer::kBufSize);
- } else {
- ConstructFilename("/proc/%d/map", pid, ibuf_, Buffer::kBufSize);
- }
- NO_INTR(fd_ = open(ibuf_, O_RDONLY));
-#elif defined(__MACH__)
- current_image_ = _dyld_image_count(); // count down from the top
- current_load_cmd_ = -1;
-#elif defined(PLATFORM_WINDOWS)
- snapshot_ = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE |
- TH32CS_SNAPMODULE32,
- GetCurrentProcessId());
- memset(&module_, 0, sizeof(module_));
-#else
- fd_ = -1; // so Valid() is always false
-#endif
-
-}
-
-ProcMapsIterator::~ProcMapsIterator() {
-#if defined(PLATFORM_WINDOWS)
- if (snapshot_ != INVALID_HANDLE_VALUE) CloseHandle(snapshot_);
-#elif defined(__MACH__)
- // no cleanup necessary!
-#else
- if (fd_ >= 0) NO_INTR(close(fd_));
-#endif
- delete dynamic_buffer_;
-}
-
-bool ProcMapsIterator::Valid() const {
-#if defined(PLATFORM_WINDOWS)
- return snapshot_ != INVALID_HANDLE_VALUE;
-#elif defined(__MACH__)
- return 1;
-#else
- return fd_ != -1;
-#endif
-}
-
-bool ProcMapsIterator::Next(uint64 *start, uint64 *end, char **flags,
- uint64 *offset, int64 *inode, char **filename) {
- return NextExt(start, end, flags, offset, inode, filename, NULL, NULL,
- NULL, NULL, NULL);
-}
-
-// This has too many arguments. It should really be building
-// a map object and returning it. The problem is that this is called
-// when the memory allocator state is undefined, hence the arguments.
-bool ProcMapsIterator::NextExt(uint64 *start, uint64 *end, char **flags,
- uint64 *offset, int64 *inode, char **filename,
- uint64 *file_mapping, uint64 *file_pages,
- uint64 *anon_mapping, uint64 *anon_pages,
- dev_t *dev) {
-
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
- do {
- // Advance to the start of the next line
- stext_ = nextline_;
-
- // See if we have a complete line in the buffer already
- nextline_ = static_cast<char *>(memchr (stext_, '\n', etext_ - stext_));
- if (!nextline_) {
- // Shift/fill the buffer so we do have a line
- int count = etext_ - stext_;
-
- // Move the current text to the start of the buffer
- memmove(ibuf_, stext_, count);
- stext_ = ibuf_;
- etext_ = ibuf_ + count;
-
- int nread = 0; // fill up buffer with text
- while (etext_ < ebuf_) {
- NO_INTR(nread = read(fd_, etext_, ebuf_ - etext_));
- if (nread > 0)
- etext_ += nread;
- else
- break;
- }
-
- // Zero out remaining characters in buffer at EOF to avoid returning
- // garbage from subsequent calls.
- if (etext_ != ebuf_ && nread == 0) {
- memset(etext_, 0, ebuf_ - etext_);
- }
- *etext_ = '\n'; // sentinel; safe because ibuf extends 1 char beyond ebuf
- nextline_ = static_cast<char *>(memchr (stext_, '\n', etext_ + 1 - stext_));
- }
- *nextline_ = 0; // turn newline into nul
- nextline_ += ((nextline_ < etext_)? 1 : 0); // skip nul if not end of text
- // stext_ now points at a nul-terminated line
- uint64 tmpstart, tmpend, tmpoffset;
- int64 tmpinode;
- int major, minor;
- unsigned filename_offset = 0;
-#if defined(__linux__)
- // for now, assume all linuxes have the same format
- if (!ParseProcMapsLine(
- stext_,
- start ? start : &tmpstart,
- end ? end : &tmpend,
- flags_,
- offset ? offset : &tmpoffset,
- &major, &minor,
- inode ? inode : &tmpinode, &filename_offset)) continue;
-#elif defined(__CYGWIN__) || defined(__CYGWIN32__)
- // cygwin is like linux, except the third field is the "entry point"
- // rather than the offset (see format_process_maps at
- // http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/fhandler_process.cc?rev=1.89&content-type=text/x-cvsweb-markup&cvsroot=src
- // Offset is always be 0 on cygwin: cygwin implements an mmap
- // by loading the whole file and then calling NtMapViewOfSection.
- // Cygwin also seems to set its flags kinda randomly; use windows default.
- char tmpflags[5];
- if (offset)
- *offset = 0;
- strcpy(flags_, "r-xp");
- if (sscanf(stext_, "%llx-%llx %4s %llx %x:%x %lld %n",
- start ? start : &tmpstart,
- end ? end : &tmpend,
- tmpflags,
- &tmpoffset,
- &major, &minor,
- inode ? inode : &tmpinode, &filename_offset) != 7) continue;
-#elif defined(__FreeBSD__)
- // For the format, see http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/fs/procfs/procfs_map.c?rev=1.31&content-type=text/x-cvsweb-markup
- tmpstart = tmpend = tmpoffset = 0;
- tmpinode = 0;
- major = minor = 0; // can't get this info in freebsd
- if (inode)
- *inode = 0; // nor this
- if (offset)
- *offset = 0; // seems like this should be in there, but maybe not
- // start end resident privateresident obj(?) prot refcnt shadowcnt
- // flags copy_on_write needs_copy type filename:
- // 0x8048000 0x804a000 2 0 0xc104ce70 r-x 1 0 0x0 COW NC vnode /bin/cat
- if (sscanf(stext_, "0x%" SCNx64 " 0x%" SCNx64 " %*d %*d %*p %3s %*d %*d 0x%*x %*s %*s %*s %n",
- start ? start : &tmpstart,
- end ? end : &tmpend,
- flags_,
- &filename_offset) != 3) continue;
-#endif
-
- // Depending on the Linux kernel being used, there may or may not be a space
- // after the inode if there is no filename. sscanf will in such situations
- // nondeterministically either fill in filename_offset or not (the results
- // differ on multiple calls in the same run even with identical arguments).
- // We don't want to wander off somewhere beyond the end of the string.
- size_t stext_length = strlen(stext_);
- if (filename_offset == 0 || filename_offset > stext_length)
- filename_offset = stext_length;
-
- // We found an entry
- if (flags) *flags = flags_;
- if (filename) *filename = stext_ + filename_offset;
- if (dev) *dev = minor | (major << 8);
-
- if (using_maps_backing_) {
- // Extract and parse physical page backing info.
- char *backing_ptr = stext_ + filename_offset +
- strlen(stext_+filename_offset);
-
- // find the second '('
- int paren_count = 0;
- while (--backing_ptr > stext_) {
- if (*backing_ptr == '(') {
- ++paren_count;
- if (paren_count >= 2) {
- uint64 tmp_file_mapping;
- uint64 tmp_file_pages;
- uint64 tmp_anon_mapping;
- uint64 tmp_anon_pages;
-
- sscanf(backing_ptr+1, "F %" SCNx64 " %" SCNd64 ") (A %" SCNx64 " %" SCNd64 ")",
- file_mapping ? file_mapping : &tmp_file_mapping,
- file_pages ? file_pages : &tmp_file_pages,
- anon_mapping ? anon_mapping : &tmp_anon_mapping,
- anon_pages ? anon_pages : &tmp_anon_pages);
- // null terminate the file name (there is a space
- // before the first (.
- backing_ptr[-1] = 0;
- break;
- }
- }
- }
- }
-
- return true;
- } while (etext_ > ibuf_);
-#elif defined(__sun__)
- // This is based on MA_READ == 4, MA_WRITE == 2, MA_EXEC == 1
- static char kPerms[8][4] = { "---", "--x", "-w-", "-wx",
- "r--", "r-x", "rw-", "rwx" };
- COMPILE_ASSERT(MA_READ == 4, solaris_ma_read_must_equal_4);
- COMPILE_ASSERT(MA_WRITE == 2, solaris_ma_write_must_equal_2);
- COMPILE_ASSERT(MA_EXEC == 1, solaris_ma_exec_must_equal_1);
- Buffer object_path;
- int nread = 0; // fill up buffer with text
- NO_INTR(nread = read(fd_, ibuf_, sizeof(prmap_t)));
- if (nread == sizeof(prmap_t)) {
- long inode_from_mapname = 0;
- prmap_t* mapinfo = reinterpret_cast<prmap_t*>(ibuf_);
- // Best-effort attempt to get the inode from the filename. I think the
- // two middle ints are major and minor device numbers, but I'm not sure.
- sscanf(mapinfo->pr_mapname, "ufs.%*d.%*d.%ld", &inode_from_mapname);
-
- if (pid_ == 0) {
- CHECK_LT(snprintf(object_path.buf_, Buffer::kBufSize,
- "/proc/self/path/%s", mapinfo->pr_mapname),
- Buffer::kBufSize);
- } else {
- CHECK_LT(snprintf(object_path.buf_, Buffer::kBufSize,
- "/proc/%d/path/%s",
- static_cast<int>(pid_), mapinfo->pr_mapname),
- Buffer::kBufSize);
- }
- ssize_t len = readlink(object_path.buf_, current_filename_, PATH_MAX);
- CHECK_LT(len, PATH_MAX);
- if (len < 0)
- len = 0;
- current_filename_[len] = '\0';
-
- if (start) *start = mapinfo->pr_vaddr;
- if (end) *end = mapinfo->pr_vaddr + mapinfo->pr_size;
- if (flags) *flags = kPerms[mapinfo->pr_mflags & 7];
- if (offset) *offset = mapinfo->pr_offset;
- if (inode) *inode = inode_from_mapname;
- if (filename) *filename = current_filename_;
- if (file_mapping) *file_mapping = 0;
- if (file_pages) *file_pages = 0;
- if (anon_mapping) *anon_mapping = 0;
- if (anon_pages) *anon_pages = 0;
- if (dev) *dev = 0;
- return true;
- }
-#elif defined(__MACH__)
- // We return a separate entry for each segment in the DLL. (TODO(csilvers):
- // can we do better?) A DLL ("image") has load-commands, some of which
- // talk about segment boundaries.
- // cf image_for_address from http://svn.digium.com/view/asterisk/team/oej/minivoicemail/dlfcn.c?revision=53912
- for (; current_image_ >= 0; current_image_--) {
- const mach_header* hdr = _dyld_get_image_header(current_image_);
- if (!hdr) continue;
- if (current_load_cmd_ < 0) // set up for this image
- current_load_cmd_ = hdr->ncmds; // again, go from the top down
-
- // We start with the next load command (we've already looked at this one).
- for (current_load_cmd_--; current_load_cmd_ >= 0; current_load_cmd_--) {
-#ifdef MH_MAGIC_64
- if (NextExtMachHelper<MH_MAGIC_64, LC_SEGMENT_64,
- struct mach_header_64, struct segment_command_64>(
- hdr, current_image_, current_load_cmd_,
- start, end, flags, offset, inode, filename,
- file_mapping, file_pages, anon_mapping,
- anon_pages, dev)) {
- return true;
- }
-#endif
- if (NextExtMachHelper<MH_MAGIC, LC_SEGMENT,
- struct mach_header, struct segment_command>(
- hdr, current_image_, current_load_cmd_,
- start, end, flags, offset, inode, filename,
- file_mapping, file_pages, anon_mapping,
- anon_pages, dev)) {
- return true;
- }
- }
- // If we get here, no more load_cmd's in this image talk about
- // segments. Go on to the next image.
- }
-#elif defined(PLATFORM_WINDOWS)
- static char kDefaultPerms[5] = "r-xp";
- BOOL ok;
- if (module_.dwSize == 0) { // only possible before first call
- module_.dwSize = sizeof(module_);
- ok = Module32First(snapshot_, &module_);
- } else {
- ok = Module32Next(snapshot_, &module_);
- }
- if (ok) {
- uint64 base_addr = reinterpret_cast<DWORD_PTR>(module_.modBaseAddr);
- if (start) *start = base_addr;
- if (end) *end = base_addr + module_.modBaseSize;
- if (flags) *flags = kDefaultPerms;
- if (offset) *offset = 0;
- if (inode) *inode = 0;
- if (filename) *filename = module_.szExePath;
- if (file_mapping) *file_mapping = 0;
- if (file_pages) *file_pages = 0;
- if (anon_mapping) *anon_mapping = 0;
- if (anon_pages) *anon_pages = 0;
- if (dev) *dev = 0;
- return true;
- }
-#endif
-
- // We didn't find anything
- return false;
-}
-
-int ProcMapsIterator::FormatLine(char* buffer, int bufsize,
- uint64 start, uint64 end, const char *flags,
- uint64 offset, int64 inode,
- const char *filename, dev_t dev) {
- // We assume 'flags' looks like 'rwxp' or 'rwx'.
- char r = (flags && flags[0] == 'r') ? 'r' : '-';
- char w = (flags && flags[0] && flags[1] == 'w') ? 'w' : '-';
- char x = (flags && flags[0] && flags[1] && flags[2] == 'x') ? 'x' : '-';
- // p always seems set on linux, so we set the default to 'p', not '-'
- char p = (flags && flags[0] && flags[1] && flags[2] && flags[3] != 'p')
- ? '-' : 'p';
-
- const int rc = snprintf(buffer, bufsize,
- "%08" PRIx64 "-%08" PRIx64 " %c%c%c%c %08" PRIx64 " %02x:%02x %-11" PRId64 " %s\n",
- start, end, r,w,x,p, offset,
- static_cast<int>(dev/256), static_cast<int>(dev%256),
- inode, filename);
- return (rc < 0 || rc >= bufsize) ? 0 : rc;
-}
-
-namespace tcmalloc {
-
-// Helper to add the list of mapped shared libraries to a profile.
-// Fill formatted "/proc/self/maps" contents into buffer 'buf' of size 'size'
-// and return the actual size occupied in 'buf'. We fill wrote_all to true
-// if we successfully wrote all proc lines to buf, false else.
-// We do not provision for 0-terminating 'buf'.
-int FillProcSelfMaps(char buf[], int size, bool* wrote_all) {
- ProcMapsIterator::Buffer iterbuf;
- ProcMapsIterator it(0, &iterbuf); // 0 means "current pid"
-
- uint64 start, end, offset;
- int64 inode;
- char *flags, *filename;
- int bytes_written = 0;
- *wrote_all = true;
- while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) {
- const int line_length = it.FormatLine(buf + bytes_written,
- size - bytes_written,
- start, end, flags, offset,
- inode, filename, 0);
- if (line_length == 0)
- *wrote_all = false; // failed to write this line out
- else
- bytes_written += line_length;
-
- }
- return bytes_written;
-}
-
-// Dump the same data as FillProcSelfMaps reads to fd.
-// It seems easier to repeat parts of FillProcSelfMaps here than to
-// reuse it via a call.
-void DumpProcSelfMaps(RawFD fd) {
- ProcMapsIterator::Buffer iterbuf;
- ProcMapsIterator it(0, &iterbuf); // 0 means "current pid"
-
- uint64 start, end, offset;
- int64 inode;
- char *flags, *filename;
- ProcMapsIterator::Buffer linebuf;
- while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) {
- int written = it.FormatLine(linebuf.buf_, sizeof(linebuf.buf_),
- start, end, flags, offset, inode, filename,
- 0);
- RawWrite(fd, linebuf.buf_, written);
- }
-}
-
-} // namespace tcmalloc
diff --git a/src/third_party/gperftools-2.5/src/base/sysinfo.h b/src/third_party/gperftools-2.5/src/base/sysinfo.h
deleted file mode 100644
index e30b0d4d1a5..00000000000
--- a/src/third_party/gperftools-2.5/src/base/sysinfo.h
+++ /dev/null
@@ -1,232 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2006, 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.
-
-// All functions here are thread-hostile due to file caching unless
-// commented otherwise.
-
-#ifndef _SYSINFO_H_
-#define _SYSINFO_H_
-
-#include <config.h>
-
-#include <time.h>
-#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
-#include <windows.h> // for DWORD
-#include <tlhelp32.h> // for CreateToolhelp32Snapshot
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for pid_t
-#endif
-#include <stddef.h> // for size_t
-#include <limits.h> // for PATH_MAX
-#include "base/basictypes.h"
-#include "base/logging.h" // for RawFD
-
-// This getenv function is safe to call before the C runtime is initialized.
-// On Windows, it utilizes GetEnvironmentVariable() and on unix it uses
-// /proc/self/environ instead calling getenv(). It's intended to be used in
-// routines that run before main(), when the state required for getenv() may
-// not be set up yet. In particular, errno isn't set up until relatively late
-// (after the pthreads library has a chance to make it threadsafe), and
-// getenv() doesn't work until then.
-// On some platforms, this call will utilize the same, static buffer for
-// repeated GetenvBeforeMain() calls. Callers should not expect pointers from
-// this routine to be long lived.
-// Note that on unix, /proc only has the environment at the time the
-// application was started, so this routine ignores setenv() calls/etc. Also
-// note it only reads the first 16K of the environment.
-extern const char* GetenvBeforeMain(const char* name);
-
-// This takes as an argument an environment-variable name (like
-// CPUPROFILE) whose value is supposed to be a file-path, and sets
-// path to that path, and returns true. Non-trivial for surprising
-// reasons, as documented in sysinfo.cc. path must have space PATH_MAX.
-extern bool GetUniquePathFromEnv(const char* env_name, char* path);
-
-extern int GetSystemCPUsCount();
-
-void SleepForMilliseconds(int milliseconds);
-
-// Return true if we're running POSIX (e.g., NPTL on Linux) threads,
-// as opposed to a non-POSIX thread library. The thing that we care
-// about is whether a thread's pid is the same as the thread that
-// spawned it. If so, this function returns true.
-// Thread-safe.
-// Note: We consider false negatives to be OK.
-bool HasPosixThreads();
-
-#ifndef SWIG // SWIG doesn't like struct Buffer and variable arguments.
-
-// A ProcMapsIterator abstracts access to /proc/maps for a given
-// process. Needs to be stack-allocatable and avoid using stdio/malloc
-// so it can be used in the google stack dumper, heap-profiler, etc.
-//
-// On Windows and Mac OS X, this iterator iterates *only* over DLLs
-// mapped into this process space. For Linux, FreeBSD, and Solaris,
-// it iterates over *all* mapped memory regions, including anonymous
-// mmaps. For other O/Ss, it is unlikely to work at all, and Valid()
-// will always return false. Also note: this routine only works on
-// FreeBSD if procfs is mounted: make sure this is in your /etc/fstab:
-// proc /proc procfs rw 0 0
-class ProcMapsIterator {
- public:
- struct Buffer {
-#ifdef __FreeBSD__
- // FreeBSD requires us to read all of the maps file at once, so
- // we have to make a buffer that's "always" big enough
- static const size_t kBufSize = 102400;
-#else // a one-line buffer is good enough
- static const size_t kBufSize = PATH_MAX + 1024;
-#endif
- char buf_[kBufSize];
- };
-
-
- // Create a new iterator for the specified pid. pid can be 0 for "self".
- explicit ProcMapsIterator(pid_t pid);
-
- // Create an iterator with specified storage (for use in signal
- // handler). "buffer" should point to a ProcMapsIterator::Buffer
- // buffer can be NULL in which case a bufer will be allocated.
- ProcMapsIterator(pid_t pid, Buffer *buffer);
-
- // Iterate through maps_backing instead of maps if use_maps_backing
- // is true. Otherwise the same as above. buffer can be NULL and
- // it will allocate a buffer itself.
- ProcMapsIterator(pid_t pid, Buffer *buffer,
- bool use_maps_backing);
-
- // Returns true if the iterator successfully initialized;
- bool Valid() const;
-
- // Returns a pointer to the most recently parsed line. Only valid
- // after Next() returns true, and until the iterator is destroyed or
- // Next() is called again. This may give strange results on non-Linux
- // systems. Prefer FormatLine() if that may be a concern.
- const char *CurrentLine() const { return stext_; }
-
- // Writes the "canonical" form of the /proc/xxx/maps info for a single
- // line to the passed-in buffer. Returns the number of bytes written,
- // or 0 if it was not able to write the complete line. (To guarantee
- // success, buffer should have size at least Buffer::kBufSize.)
- // Takes as arguments values set via a call to Next(). The
- // "canonical" form of the line (taken from linux's /proc/xxx/maps):
- // <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)> +
- // <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the
- // eg
- // 08048000-0804c000 r-xp 00000000 03:01 3793678 /bin/cat
- // If you don't have the dev_t (dev), feel free to pass in 0.
- // (Next() doesn't return a dev_t, though NextExt does.)
- //
- // Note: if filename and flags were obtained via a call to Next(),
- // then the output of this function is only valid if Next() returned
- // true, and only until the iterator is destroyed or Next() is
- // called again. (Since filename, at least, points into CurrentLine.)
- static int FormatLine(char* buffer, int bufsize,
- uint64 start, uint64 end, const char *flags,
- uint64 offset, int64 inode, const char *filename,
- dev_t dev);
-
- // Find the next entry in /proc/maps; return true if found or false
- // if at the end of the file.
- //
- // Any of the result pointers can be NULL if you're not interested
- // in those values.
- //
- // If "flags" and "filename" are passed, they end up pointing to
- // storage within the ProcMapsIterator that is valid only until the
- // iterator is destroyed or Next() is called again. The caller may
- // modify the contents of these strings (up as far as the first NUL,
- // and only until the subsequent call to Next()) if desired.
-
- // The offsets are all uint64 in order to handle the case of a
- // 32-bit process running on a 64-bit kernel
- //
- // IMPORTANT NOTE: see top-of-class notes for details about what
- // mapped regions Next() iterates over, depending on O/S.
- // TODO(csilvers): make flags and filename const.
- bool Next(uint64 *start, uint64 *end, char **flags,
- uint64 *offset, int64 *inode, char **filename);
-
- bool NextExt(uint64 *start, uint64 *end, char **flags,
- uint64 *offset, int64 *inode, char **filename,
- uint64 *file_mapping, uint64 *file_pages,
- uint64 *anon_mapping, uint64 *anon_pages,
- dev_t *dev);
-
- ~ProcMapsIterator();
-
- private:
- void Init(pid_t pid, Buffer *buffer, bool use_maps_backing);
-
- char *ibuf_; // input buffer
- char *stext_; // start of text
- char *etext_; // end of text
- char *nextline_; // start of next line
- char *ebuf_; // end of buffer (1 char for a nul)
-#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
- HANDLE snapshot_; // filehandle on dll info
- // In a change from the usual W-A pattern, there is no A variant of
- // MODULEENTRY32. Tlhelp32.h #defines the W variant, but not the A.
- // We want the original A variants, and this #undef is the only
- // way I see to get them. Redefining it when we're done prevents us
- // from affecting other .cc files.
-# ifdef MODULEENTRY32 // Alias of W
-# undef MODULEENTRY32
- MODULEENTRY32 module_; // info about current dll (and dll iterator)
-# define MODULEENTRY32 MODULEENTRY32W
-# else // It's the ascii, the one we want.
- MODULEENTRY32 module_; // info about current dll (and dll iterator)
-# endif
-#elif defined(__MACH__)
- int current_image_; // dll's are called "images" in macos parlance
- int current_load_cmd_; // the segment of this dll we're examining
-#elif defined(__sun__) // Solaris
- int fd_;
- char current_filename_[PATH_MAX];
-#else
- int fd_; // filehandle on /proc/*/maps
-#endif
- pid_t pid_;
- char flags_[10];
- Buffer* dynamic_buffer_; // dynamically-allocated Buffer
- bool using_maps_backing_; // true if we are looking at maps_backing instead of maps.
-};
-
-#endif /* #ifndef SWIG */
-
-// Helper routines
-
-namespace tcmalloc {
-int FillProcSelfMaps(char buf[], int size, bool* wrote_all);
-void DumpProcSelfMaps(RawFD fd);
-}
-
-#endif /* #ifndef _SYSINFO_H_ */
diff --git a/src/third_party/gperftools-2.5/src/base/thread_annotations.h b/src/third_party/gperftools-2.5/src/base/thread_annotations.h
deleted file mode 100644
index f57b2999ee7..00000000000
--- a/src/third_party/gperftools-2.5/src/base/thread_annotations.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// 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: Le-Chun Wu
-//
-// This header file contains the macro definitions for thread safety
-// annotations that allow the developers to document the locking policies
-// of their multi-threaded code. The annotations can also help program
-// analysis tools to identify potential thread safety issues.
-//
-// The annotations are implemented using GCC's "attributes" extension.
-// Using the macros defined here instead of the raw GCC attributes allows
-// for portability and future compatibility.
-//
-// This functionality is not yet fully implemented in perftools,
-// but may be one day.
-
-#ifndef BASE_THREAD_ANNOTATIONS_H_
-#define BASE_THREAD_ANNOTATIONS_H_
-
-
-#if defined(__GNUC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) \
- && defined(__SUPPORT_TS_ANNOTATION__) && (!defined(SWIG))
-#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
-#else
-#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
-#endif
-
-
-// Document if a shared variable/field needs to be protected by a lock.
-// GUARDED_BY allows the user to specify a particular lock that should be
-// held when accessing the annotated variable, while GUARDED_VAR only
-// indicates a shared variable should be guarded (by any lock). GUARDED_VAR
-// is primarily used when the client cannot express the name of the lock.
-#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
-#define GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(guarded)
-
-// Document if the memory location pointed to by a pointer should be guarded
-// by a lock when dereferencing the pointer. Similar to GUARDED_VAR,
-// PT_GUARDED_VAR is primarily used when the client cannot express the name
-// of the lock. Note that a pointer variable to a shared memory location
-// could itself be a shared variable. For example, if a shared global pointer
-// q, which is guarded by mu1, points to a shared memory location that is
-// guarded by mu2, q should be annotated as follows:
-// int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
-#define PT_GUARDED_BY(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded_by(x))
-#define PT_GUARDED_VAR \
- THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded)
-
-// Document the acquisition order between locks that can be held
-// simultaneously by a thread. For any two locks that need to be annotated
-// to establish an acquisition order, only one of them needs the annotation.
-// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
-// and ACQUIRED_BEFORE.)
-#define ACQUIRED_AFTER(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(x))
-#define ACQUIRED_BEFORE(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(x))
-
-// The following three annotations document the lock requirements for
-// functions/methods.
-
-// Document if a function expects certain locks to be held before it is called
-#define EXCLUSIVE_LOCKS_REQUIRED(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x))
-
-#define SHARED_LOCKS_REQUIRED(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(x))
-
-// Document the locks acquired in the body of the function. These locks
-// cannot be held when calling this function (as google3's Mutex locks are
-// non-reentrant).
-#define LOCKS_EXCLUDED(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x))
-
-// Document the lock the annotated function returns without acquiring it.
-#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
-
-// Document if a class/type is a lockable type (such as the Mutex class).
-#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable)
-
-// Document if a class is a scoped lockable type (such as the MutexLock class).
-#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
-
-// The following annotations specify lock and unlock primitives.
-#define EXCLUSIVE_LOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock(x))
-
-#define SHARED_LOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_lock(x))
-
-#define EXCLUSIVE_TRYLOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock(x))
-
-#define SHARED_TRYLOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock(x))
-
-#define UNLOCK_FUNCTION(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(unlock(x))
-
-// An escape hatch for thread safety analysis to ignore the annotated function.
-#define NO_THREAD_SAFETY_ANALYSIS \
- THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
-
-#endif // BASE_THREAD_ANNOTATIONS_H_
diff --git a/src/third_party/gperftools-2.5/src/base/thread_lister.c b/src/third_party/gperftools-2.5/src/base/thread_lister.c
deleted file mode 100644
index 9dc8d721892..00000000000
--- a/src/third_party/gperftools-2.5/src/base/thread_lister.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Copyright (c) 2005-2007, 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: Markus Gutschke
- */
-
-#include "config.h"
-
-#include "base/thread_lister.h"
-
-#include <stdio.h> /* needed for NULL on some powerpc platforms (?!) */
-#include <sys/types.h>
-#include <unistd.h> /* for getpid */
-
-#ifdef HAVE_SYS_PRCTL
-# include <sys/prctl.h>
-#endif
-
-#include "base/linuxthreads.h"
-/* Include other thread listers here that define THREADS macro
- * only when they can provide a good implementation.
- */
-
-#ifndef THREADS
-
-/* Default trivial thread lister for single-threaded applications,
- * or if the multi-threading code has not been ported, yet.
- */
-
-int TCMalloc_ListAllProcessThreads(void *parameter,
- ListAllProcessThreadsCallBack callback, ...) {
- int rc;
- va_list ap;
- pid_t pid;
-
-#ifdef HAVE_SYS_PRCTL
- int dumpable = prctl(PR_GET_DUMPABLE, 0);
- if (!dumpable)
- prctl(PR_SET_DUMPABLE, 1);
-#endif
- va_start(ap, callback);
- pid = getpid();
- rc = callback(parameter, 1, &pid, ap);
- va_end(ap);
-#ifdef HAVE_SYS_PRCTL
- if (!dumpable)
- prctl(PR_SET_DUMPABLE, 0);
-#endif
- return rc;
-}
-
-int TCMalloc_ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) {
- return 1;
-}
-
-#endif /* ifndef THREADS */
diff --git a/src/third_party/gperftools-2.5/src/base/thread_lister.h b/src/third_party/gperftools-2.5/src/base/thread_lister.h
deleted file mode 100644
index 6e70b89fef5..00000000000
--- a/src/third_party/gperftools-2.5/src/base/thread_lister.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-/* Copyright (c) 2005-2007, 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: Markus Gutschke
- */
-
-#ifndef _THREAD_LISTER_H
-#define _THREAD_LISTER_H
-
-#include <stdarg.h>
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef int (*ListAllProcessThreadsCallBack)(void *parameter,
- int num_threads,
- pid_t *thread_pids,
- va_list ap);
-
-/* This function gets the list of all linux threads of the current process
- * passes them to the 'callback' along with the 'parameter' pointer; at the
- * call back call time all the threads are paused via
- * PTRACE_ATTACH.
- * The callback is executed from a separate thread which shares only the
- * address space, the filesystem, and the filehandles with the caller. Most
- * notably, it does not share the same pid and ppid; and if it terminates,
- * the rest of the application is still there. 'callback' is supposed to do
- * or arrange for TCMalloc_ResumeAllProcessThreads. This happens automatically, if
- * the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous
- * signals are blocked. If the 'callback' decides to unblock them, it must
- * ensure that they cannot terminate the application, or that
- * TCMalloc_ResumeAllProcessThreads will get called.
- * It is an error for the 'callback' to make any library calls that could
- * acquire locks. Most notably, this means that most system calls have to
- * avoid going through libc. Also, this means that it is not legal to call
- * exit() or abort().
- * We return -1 on error and the return value of 'callback' on success.
- */
-int TCMalloc_ListAllProcessThreads(void *parameter,
- ListAllProcessThreadsCallBack callback, ...);
-
-/* This function resumes the list of all linux threads that
- * TCMalloc_ListAllProcessThreads pauses before giving to its
- * callback. The function returns non-zero if at least one thread was
- * suspended and has now been resumed.
- */
-int TCMalloc_ResumeAllProcessThreads(int num_threads, pid_t *thread_pids);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _THREAD_LISTER_H */
diff --git a/src/third_party/gperftools-2.5/src/base/vdso_support.cc b/src/third_party/gperftools-2.5/src/base/vdso_support.cc
deleted file mode 100644
index 730df3011d6..00000000000
--- a/src/third_party/gperftools-2.5/src/base/vdso_support.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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.
-//
-// VDSOSupport -- a class representing kernel VDSO (if present).
-//
-
-#include "base/vdso_support.h"
-
-#ifdef HAVE_VDSO_SUPPORT // defined in vdso_support.h
-
-#include <fcntl.h>
-#include <stddef.h> // for ptrdiff_t
-
-#include "base/atomicops.h" // for MemoryBarrier
-#include "base/linux_syscall_support.h"
-#include "base/logging.h"
-#include "base/dynamic_annotations.h"
-#include "base/basictypes.h" // for COMPILE_ASSERT
-
-using base::subtle::MemoryBarrier;
-
-#ifndef AT_SYSINFO_EHDR
-#define AT_SYSINFO_EHDR 33
-#endif
-
-namespace base {
-
-const void *VDSOSupport::vdso_base_ = ElfMemImage::kInvalidBase;
-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_ == ElfMemImage::kInvalidBase ? Init() : vdso_base_) {
-}
-
-// NOTE: we can't use GoogleOnceInit() below, because we can be
-// called by tcmalloc, and none of the *once* stuff may be functional yet.
-//
-// In addition, we hope that the VDSOSupportHelper constructor
-// causes this code to run before there are any threads, and before
-// InitGoogle() has executed any chroot or setuid calls.
-//
-// Finally, even if there is a race here, it is harmless, because
-// the operation should be idempotent.
-const void *VDSOSupport::Init() {
- 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
- // Valgrind zapping. So we check for Valgrind separately.
- if (RunningOnValgrind()) {
- vdso_base_ = NULL;
- return NULL;
- }
- int fd = open("/proc/self/auxv", O_RDONLY);
- if (fd == -1) {
- // Kernel too old to have a VDSO.
- vdso_base_ = NULL;
- return NULL;
- }
- ElfW(auxv_t) aux;
- while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) {
- if (aux.a_type == AT_SYSINFO_EHDR) {
- COMPILE_ASSERT(sizeof(vdso_base_) == sizeof(aux.a_un.a_val),
- unexpected_sizeof_pointer_NE_sizeof_a_val);
- vdso_base_ = reinterpret_cast<void *>(aux.a_un.a_val);
- break;
- }
- }
- close(fd);
- if (vdso_base_ == ElfMemImage::kInvalidBase) {
- // Didn't find AT_SYSINFO_EHDR in auxv[].
- vdso_base_ = NULL;
- }
- }
- return vdso_base_;
-}
-
-const void *VDSOSupport::SetBase(const void *base) {
- CHECK(base != ElfMemImage::kInvalidBase);
- const void *old_base = vdso_base_;
- vdso_base_ = base;
- image_.Init(base);
- return old_base;
-}
-
-bool VDSOSupport::LookupSymbol(const char *name,
- const char *version,
- int type,
- SymbolInfo *info) const {
- return image_.LookupSymbol(name, version, type, info);
-}
-
-bool VDSOSupport::LookupSymbolByAddress(const void *address,
- SymbolInfo *info_out) const {
- return image_.LookupSymbolByAddress(address, info_out);
-}
-
-// We need to make sure VDSOSupport::Init() is called before
-// the main() runs, since it might do something like setuid or
-// chroot. If VDSOSupport
-// is used in any global constructor, this will happen, since
-// VDSOSupport's constructor calls Init. But if not, we need to
-// ensure it here, with a global constructor of our own. This
-// is an allowed exception to the normal rule against non-trivial
-// global constructors.
-static class VDSOInitHelper {
- public:
- VDSOInitHelper() { VDSOSupport::Init(); }
-} vdso_init_helper;
-}
-
-#endif // HAVE_VDSO_SUPPORT
diff --git a/src/third_party/gperftools-2.5/src/base/vdso_support.h b/src/third_party/gperftools-2.5/src/base/vdso_support.h
deleted file mode 100644
index c1209a47f13..00000000000
--- a/src/third_party/gperftools-2.5/src/base/vdso_support.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// 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.
-//
-// VDSO stands for "Virtual Dynamic Shared Object" -- a page of
-// executable code, which looks like a shared library, but doesn't
-// necessarily exist anywhere on disk, and which gets mmap()ed into
-// every process by kernels which support VDSO, such as 2.6.x for 32-bit
-// executables, and 2.6.24 and above for 64-bit executables.
-//
-// More details could be found here:
-// http://www.trilithium.com/johan/2005/08/linux-gate/
-//
-// VDSOSupport -- a class representing kernel VDSO (if present).
-//
-// Example usage:
-// VDSOSupport vdso;
-// VDSOSupport::SymbolInfo info;
-// typedef (*FN)(unsigned *, void *, void *);
-// FN fn = NULL;
-// if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) {
-// fn = reinterpret_cast<FN>(info.address);
-// }
-
-#ifndef BASE_VDSO_SUPPORT_H_
-#define BASE_VDSO_SUPPORT_H_
-
-#include <config.h>
-#include "base/basictypes.h"
-#include "base/elf_mem_image.h"
-
-#ifdef HAVE_ELF_MEM_IMAGE
-
-#define HAVE_VDSO_SUPPORT 1
-
-#include <stdlib.h> // for NULL
-
-namespace base {
-
-// NOTE: this class may be used from within tcmalloc, and can not
-// use any memory allocation routines.
-class VDSOSupport {
- public:
- 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 { 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
- // 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 VDSO 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;
-
- // Used only for testing. Replace real VDSO base with a mock.
- // Returns previous value of vdso_base_. After you are done testing,
- // you are expected to call SetBase() with previous value, in order to
- // reset state to the way it was.
- const void *SetBase(const void *s);
-
- // Computes vdso_base_ and returns it. Should be called as early as
- // possible; before any thread creation, chroot or setuid.
- static const void *Init();
-
- private:
- // image_ represents VDSO ELF image in memory.
- // image_.ehdr_ == NULL implies there is no VDSO.
- ElfMemImage image_;
-
- // Cached value of auxv AT_SYSINFO_EHDR, computed once.
- // This is a tri-state:
- // kInvalidBase => value hasn't been determined yet.
- // 0 => there is no VDSO.
- // else => vma of VDSO Elf{32,64}_Ehdr.
- //
- // When testing with mock VDSO, low bit is set.
- // The low bit is always available because vdso_base_ is
- // page-aligned.
- static const void *vdso_base_;
-
- DISALLOW_COPY_AND_ASSIGN(VDSOSupport);
-};
-
-} // namespace base
-
-#endif // HAVE_ELF_MEM_IMAGE
-
-#endif // BASE_VDSO_SUPPORT_H_
diff --git a/src/third_party/gperftools-2.5/src/central_freelist.cc b/src/third_party/gperftools-2.5/src/central_freelist.cc
deleted file mode 100644
index 11b190dcfee..00000000000
--- a/src/third_party/gperftools-2.5/src/central_freelist.cc
+++ /dev/null
@@ -1,387 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: 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_ <= max_cache_size_);
-}
-
-void CentralFreeList::ReleaseListToSpans(void* start) {
- while (start) {
- void *next = SLL_Next(start);
- ReleaseToSpans(start);
- start = next;
- }
-}
-
-// MapObjectToSpan should logically be part of ReleaseToSpans. But
-// this triggers an optimization bug in gcc 4.5.0. Moving to a
-// separate function, and making sure that function isn't inlined,
-// seems to fix the problem. It also should be fixed for gcc 4.5.1.
-static
-#if __GNUC__ == 4 && __GNUC_MINOR__ == 5 && __GNUC_PATCHLEVEL__ == 0
-__attribute__ ((noinline))
-#endif
-Span* MapObjectToSpan(void* object) {
- const PageID p = reinterpret_cast<uintptr_t>(object) >> kPageShift;
- Span* span = Static::pageheap()->GetDescriptor(p);
- return span;
-}
-
-void CentralFreeList::ReleaseToSpans(void* object) {
- Span* span = MapObjectToSpan(object);
- ASSERT(span != NULL);
- ASSERT(span->refcount > 0);
-
- // If span is empty, move it to non-empty list
- if (span->objects == NULL) {
- tcmalloc::DLL_Remove(span);
- tcmalloc::DLL_Prepend(&nonempty_, span);
- Event(span, 'N', 0);
- }
-
- // The following check is expensive, so it is disabled by default
- if (false) {
- // Check that object does not occur in list
- int got = 0;
- for (void* p = span->objects; p != NULL; p = *((void**) p)) {
- ASSERT(p != object);
- got++;
- }
- ASSERT(got + span->refcount ==
- (span->length<<kPageShift) /
- Static::sizemap()->ByteSizeForClass(span->sizeclass));
- }
-
- counter_++;
- span->refcount--;
- if (span->refcount == 0) {
- Event(span, '#', 0);
- 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();
- {
- SpinLockHolder h(Static::pageheap_lock());
- Static::pageheap()->Delete(span);
- }
- lock_.Lock();
- } else {
- *(reinterpret_cast<void**>(object)) = span->objects;
- span->objects = object;
- }
-}
-
-bool CentralFreeList::EvictRandomSizeClass(
- int locked_size_class, bool force) {
- static int race_counter = 0;
- int t = race_counter++; // Updated without a lock, but who cares.
- if (t >= kNumClasses) {
- while (t >= kNumClasses) {
- t -= kNumClasses;
- }
- race_counter = t;
- }
- ASSERT(t >= 0);
- ASSERT(t < kNumClasses);
- if (t == locked_size_class) return false;
- return Static::central_cache()[t].ShrinkCache(locked_size_class, force);
-}
-
-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_ == 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)) {
- // Succeeded in evicting, we're going to make our cache larger.
- // However, we may have dropped and re-acquired the lock in
- // 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_ < max_cache_size_) {
- cache_size_++;
- return true;
- }
- }
- return false;
-}
-
-
-namespace {
-class LockInverter {
- private:
- SpinLock *held_, *temp_;
- public:
- inline explicit LockInverter(SpinLock* held, SpinLock *temp)
- : held_(held), temp_(temp) { held_->Unlock(); temp_->Lock(); }
- inline ~LockInverter() { temp_->Unlock(); held_->Lock(); }
-};
-}
-
-// This function is marked as NO_THREAD_SAFETY_ANALYSIS because it uses
-// LockInverter to release one lock and acquire another in scoped-lock
-// style, which our current annotation/analysis does not support.
-bool CentralFreeList::ShrinkCache(int locked_size_class, bool force)
- NO_THREAD_SAFETY_ANALYSIS {
- // Start with a quick check without taking a lock.
- if (cache_size_ == 0) return false;
- // We don't evict from a full cache unless we are 'forcing'.
- if (force == false && used_slots_ == cache_size_) return false;
-
- // Grab lock, but first release the other lock held by this thread. We use
- // the lock inverter to ensure that we never hold two size class locks
- // concurrently. That can create a deadlock because there is no well
- // defined nesting order.
- LockInverter li(&Static::central_cache()[locked_size_class].lock_, &lock_);
- ASSERT(used_slots_ <= cache_size_);
- ASSERT(0 <= cache_size_);
- if (cache_size_ == 0) return false;
- if (used_slots_ == cache_size_) {
- if (force == false) return false;
- // ReleaseListToSpans releases the lock, so we have to make all the
- // updates to the central list before calling it.
- cache_size_--;
- used_slots_--;
- ReleaseListToSpans(tc_slots_[used_slots_].head);
- return true;
- }
- cache_size_--;
- return true;
-}
-
-void CentralFreeList::InsertRange(void *start, void *end, int N) {
- SpinLockHolder h(&lock_);
- if (N == Static::sizemap()->num_objects_to_move(size_class_) &&
- MakeCacheSpace()) {
- int slot = used_slots_++;
- ASSERT(slot >=0);
- ASSERT(slot < max_cache_size_);
- TCEntry *entry = &tc_slots_[slot];
- entry->head = start;
- entry->tail = end;
- return;
- }
- ReleaseListToSpans(start);
-}
-
-int CentralFreeList::RemoveRange(void **start, void **end, int N) {
- ASSERT(N > 0);
- lock_.Lock();
- if (N == Static::sizemap()->num_objects_to_move(size_class_) &&
- used_slots_ > 0) {
- int slot = --used_slots_;
- ASSERT(slot >= 0);
- TCEntry *entry = &tc_slots_[slot];
- *start = entry->head;
- *end = entry->tail;
- lock_.Unlock();
- return N;
- }
-
- int result = 0;
- *start = NULL;
- *end = NULL;
- // TODO: Prefetch multiple TCEntries?
- result = FetchFromOneSpansSafe(N, start, end);
- if (result != 0) {
- while (result < N) {
- int n;
- void* head = NULL;
- void* tail = NULL;
- n = FetchFromOneSpans(N - result, &head, &tail);
- if (!n) break;
- result += n;
- SLL_PushRange(start, head, tail);
- }
- }
- lock_.Unlock();
- return result;
-}
-
-
-int CentralFreeList::FetchFromOneSpansSafe(int N, void **start, void **end) {
- int result = FetchFromOneSpans(N, start, end);
- if (!result) {
- Populate();
- result = FetchFromOneSpans(N, start, end);
- }
- return result;
-}
-
-int CentralFreeList::FetchFromOneSpans(int N, void **start, void **end) {
- if (tcmalloc::DLL_IsEmpty(&nonempty_)) return 0;
- Span* span = nonempty_.next;
-
- ASSERT(span->objects != NULL);
-
- int result = 0;
- void *prev, *curr;
- curr = span->objects;
- do {
- prev = curr;
- curr = *(reinterpret_cast<void**>(curr));
- } while (++result < N && curr != NULL);
-
- if (curr == NULL) {
- // Move to empty list
- tcmalloc::DLL_Remove(span);
- tcmalloc::DLL_Prepend(&empty_, span);
- Event(span, 'E', 0);
- }
-
- *start = span->objects;
- *end = prev;
- span->objects = curr;
- SLL_SetNext(*end, NULL);
- span->refcount += result;
- counter_ -= result;
- return result;
-}
-
-// Fetch memory from the system and add to the central cache freelist.
-void CentralFreeList::Populate() {
- // Release central list lock while operating on pageheap
- lock_.Unlock();
- const size_t npages = Static::sizemap()->class_to_pages(size_class_);
-
- Span* span;
- {
- SpinLockHolder h(Static::pageheap_lock());
- span = Static::pageheap()->New(npages);
- if (span) Static::pageheap()->RegisterSizeClass(span, size_class_);
- }
- if (span == NULL) {
- Log(kLog, __FILE__, __LINE__,
- "tcmalloc: allocation failed", npages << kPageShift);
- lock_.Lock();
- return;
- }
- ASSERT(span->length == npages);
- // Cache sizeclass info eagerly. Locking is not necessary.
- // (Instead of being eager, we could just replace any stale info
- // about this span, but that seems to be no better in practice.)
- for (int i = 0; i < npages; i++) {
- Static::pageheap()->CacheSizeClass(span->start + i, size_class_);
- }
-
- // Split the block into pieces and add to the free-list
- // TODO: coloring of objects to avoid cache conflicts?
- void** tail = &span->objects;
- char* ptr = reinterpret_cast<char*>(span->start << kPageShift);
- char* limit = ptr + (npages << kPageShift);
- const size_t size = Static::sizemap()->ByteSizeForClass(size_class_);
- int num = 0;
- while (ptr + size <= limit) {
- *tail = ptr;
- tail = reinterpret_cast<void**>(ptr);
- ptr += size;
- num++;
- }
- ASSERT(ptr <= limit);
- *tail = NULL;
- span->refcount = 0; // No sub-object in use yet
-
- // Add span to list of non-empty spans
- lock_.Lock();
- tcmalloc::DLL_Prepend(&nonempty_, span);
- ++num_spans_;
- counter_ += num;
-}
-
-int CentralFreeList::tc_length() {
- SpinLockHolder h(&lock_);
- 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/src/third_party/gperftools-2.5/src/central_freelist.h b/src/third_party/gperftools-2.5/src/central_freelist.h
deleted file mode 100644
index 4085ee41b98..00000000000
--- a/src/third_party/gperftools-2.5/src/central_freelist.h
+++ /dev/null
@@ -1,217 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-
-#ifndef TCMALLOC_CENTRAL_FREELIST_H_
-#define TCMALLOC_CENTRAL_FREELIST_H_
-
-#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"
-#include "span.h"
-
-namespace tcmalloc {
-
-// Data kept per size-class in central cache.
-class CentralFreeList {
- public:
- // A CentralFreeList may be used before its constructor runs.
- // So we prevent lock_'s constructor from doing anything to the
- // lock_ state.
- CentralFreeList() : lock_(base::LINKER_INITIALIZED) { }
-
- void Init(size_t cl);
-
- // These methods all do internal locking.
-
- // Insert the specified range into the central freelist. N is the number of
- // elements in the range. RemoveRange() is the opposite operation.
- void InsertRange(void *start, void *end, int N);
-
- // Returns the actual number of fetched elements and sets *start and *end.
- int RemoveRange(void **start, void **end, int N);
-
- // Returns the number of free objects in cache.
- int length() {
- SpinLockHolder h(&lock_);
- return counter_;
- }
-
- // Returns the number of free objects in the transfer cache.
- int tc_length();
-
- // Returns the number of spans in both the empty and nonempty freelists.
- int spans() {
- SpinLockHolder h(&lock_);
- return num_spans_;
- }
-
- // 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();
-
- // Lock/Unlock the internal SpinLock. Used on the pthread_atfork call
- // to set the lock in a consistent state before the fork.
- void Lock() {
- lock_.Lock();
- }
-
- void Unlock() {
- lock_.Unlock();
- }
-
- private:
- // TransferCache is used to cache transfers of
- // sizemap.num_objects_to_move(size_class) back and forth between
- // thread caches and the central cache for a given size class.
- struct TCEntry {
- void *head; // Head of chain of objects.
- void *tail; // Tail of chain of objects.
- };
-
- // 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 kMaxNumTransferEntries = 0;
-#else
- // 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
- // Remove object from cache and return.
- // Return NULL if no free entries in cache.
- int FetchFromOneSpans(int N, void **start, void **end) EXCLUSIVE_LOCKS_REQUIRED(lock_);
-
- // REQUIRES: lock_ is held
- // Remove object from cache and return. Fetches
- // from pageheap if cache is empty. Only returns
- // NULL on allocation failure.
- int FetchFromOneSpansSafe(int N, void **start, void **end) EXCLUSIVE_LOCKS_REQUIRED(lock_);
-
- // REQUIRES: lock_ is held
- // Release a linked list of objects to spans.
- // May temporarily release lock_.
- void ReleaseListToSpans(void *start) EXCLUSIVE_LOCKS_REQUIRED(lock_);
-
- // REQUIRES: lock_ is held
- // Release an object to spans.
- // May temporarily release lock_.
- void ReleaseToSpans(void* object) EXCLUSIVE_LOCKS_REQUIRED(lock_);
-
- // REQUIRES: lock_ is held
- // Populate cache by fetching from the page heap.
- // May temporarily release lock_.
- void Populate() EXCLUSIVE_LOCKS_REQUIRED(lock_);
-
- // REQUIRES: lock is held.
- // Tries to make room for a TCEntry. If the cache is full it will try to
- // expand it at the cost of some other cache size. Return false if there is
- // no space.
- bool MakeCacheSpace() EXCLUSIVE_LOCKS_REQUIRED(lock_);
-
- // REQUIRES: lock_ for locked_size_class is held.
- // Picks a "random" size class to steal TCEntry slot from. In reality it
- // just iterates over the sizeclasses but does so without taking a lock.
- // Returns true on success.
- // May temporarily lock a "random" size class.
- static bool EvictRandomSizeClass(int locked_size_class, bool force);
-
- // REQUIRES: lock_ is *not* held.
- // Tries to shrink the Cache. If force is true it will relase objects to
- // spans if it allows it to shrink the cache. Return false if it failed to
- // shrink the cache. Decrements cache_size_ on succeess.
- // May temporarily take lock_. If it takes lock_, the locked_size_class
- // lock is released to keep the thread from holding two size class locks
- // concurrently which could lead to a deadlock.
- bool ShrinkCache(int locked_size_class, bool force) LOCKS_EXCLUDED(lock_);
-
- // This lock protects all the data members. cached_entries and cache_size_
- // may be looked at without holding the lock.
- SpinLock lock_;
-
- // We keep linked lists of empty and non-empty spans.
- 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. 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.
- int32_t used_slots_;
- // The current number of slots for this size class. This is an
- // 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
-// compilers (such as MSVC) don't like it when the padding is 0, I use
-// template specialization to remove the padding entirely when
-// sizeof(CentralFreeList) is a multiple of 64.
-template<int kFreeListSizeMod64>
-class CentralFreeListPaddedTo : public CentralFreeList {
- private:
- char pad_[64 - kFreeListSizeMod64];
-};
-
-template<>
-class CentralFreeListPaddedTo<0> : public CentralFreeList {
-};
-
-class CentralFreeListPadded : public CentralFreeListPaddedTo<
- sizeof(CentralFreeList) % 64> {
-};
-
-} // namespace tcmalloc
-
-#endif // TCMALLOC_CENTRAL_FREELIST_H_
diff --git a/src/third_party/gperftools-2.5/src/common.cc b/src/third_party/gperftools-2.5/src/common.cc
deleted file mode 100644
index 215e6b1bf17..00000000000
--- a/src/third_party/gperftools-2.5/src/common.cc
+++ /dev/null
@@ -1,285 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-
-#include <stdlib.h> // for getenv and strtol
-#include "config.h"
-#include "common.h"
-#include "system-alloc.h"
-#include "base/spinlock.h"
-#include "getenv_safe.h" // TCMallocGetenvSafe
-
-namespace tcmalloc {
-
-// Define the maximum number of object per classe type to transfer between
-// thread and central caches.
-static int32 FLAGS_tcmalloc_transfer_num_objects;
-
-static const int32 kDefaultTransferNumObjecs = 512;
-static const int32 kTargetTransferBytes = 8 * 1024;
-
-// The init function is provided to explicit initialize the variable value
-// from the env. var to avoid C++ global construction that might defer its
-// initialization after a malloc/new call.
-static inline void InitTCMallocTransferNumObjects()
-{
- if (UNLIKELY(FLAGS_tcmalloc_transfer_num_objects == 0)) {
- const char *envval = TCMallocGetenvSafe("TCMALLOC_TRANSFER_NUM_OBJ");
- FLAGS_tcmalloc_transfer_num_objects = !envval ? kDefaultTransferNumObjecs :
- strtol(envval, NULL, 10);
- }
-}
-
-// Note: the following only works for "n"s that fit in 32-bits, but
-// that is fine since we only use it for small sizes.
-static inline int LgFloor(size_t n) {
- int log = 0;
- for (int i = 4; i >= 0; --i) {
- int shift = (1 << i);
- size_t x = n >> shift;
- if (x != 0) {
- n = x;
- log += shift;
- }
- }
- ASSERT(n == 1);
- return log;
-}
-
-int AlignmentForSize(size_t size) {
- int alignment = kAlignment;
- 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;
- } else if (size >= kMinAlign) {
- // We need an alignment of at least 16 bytes to satisfy
- // requirements for some SSE types.
- alignment = kMinAlign;
- }
- // Maximum alignment allowed is page size alignment.
- if (alignment > kPageSize) {
- alignment = kPageSize;
- }
- CHECK_CONDITION(size < kMinAlign || alignment >= kMinAlign);
- CHECK_CONDITION((alignment & (alignment - 1)) == 0);
- return alignment;
-}
-
-int SizeMap::NumMoveSize(size_t size) {
- if (size == 0) return 0;
- // Use a min of (8k, 2 count) transfers between thread and central caches.
- int num = kTargetTransferBytes / size;
- if (num < 2) num = 2;
-
- // Avoid bringing too many objects into small object free lists.
- // If this value is too large:
- // - We waste memory with extra objects sitting in the thread caches.
- // - The central freelist holds its lock for too long while
- // building a linked list of objects, slowing down the allocations
- // of other threads.
- // If this value is too small:
- // - We go to the central freelist too often and we have to acquire
- // its lock each time.
- // This value strikes a balance between the constraints above.
- if (num > FLAGS_tcmalloc_transfer_num_objects)
- num = FLAGS_tcmalloc_transfer_num_objects;
-
- return num;
-}
-
-// Initialize the mapping arrays
-void SizeMap::Init() {
- InitTCMallocTransferNumObjects();
-
- // Do some sanity checking on add_amount[]/shift_amount[]/class_array[]
- if (ClassIndex(0) != 0) {
- Log(kCrash, __FILE__, __LINE__,
- "Invalid class index for size 0", ClassIndex(0));
- }
- if (ClassIndex(kMaxSize) >= sizeof(class_array_)) {
- Log(kCrash, __FILE__, __LINE__,
- "Invalid class index for kMaxSize", ClassIndex(kMaxSize));
- }
-
- // Compute the size classes we want to use
- int sc = 1; // Next size class to assign
- size_t potential_merge_sizes[kMaxSize];
- int potential_merge_count = 0;
- int alignment = kAlignment;
- CHECK_CONDITION(kAlignment <= kMinAlign);
- for (size_t size = kAlignment; size <= kMaxSize; size += alignment) {
- alignment = AlignmentForSize(size);
- CHECK_CONDITION((size % alignment) == 0);
-
- int min_objects_per_span = kTargetTransferBytes / size;
- size_t span_size = 0;
- do {
- span_size += kPageSize;
- // Allocate enough pages so leftover is less than 1/8 of total.
- // This bounds wasted space to at most 12.5%.
- while ((span_size % size) > (span_size >> 3)) {
- span_size += 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 ((span_size / size) < min_objects_per_span);
- const size_t my_pages = span_size >> kPageShift;
-
- bool merge = (potential_merge_count != 0);
- for (int i = 0; i < potential_merge_count; i++) {
- // See if we can merge this into the previous class(es) without
- // the fragmentation of any of them going over 12.5%.
- int objects_per_span = span_size / size;
- size_t waste = span_size - (potential_merge_sizes[i] * objects_per_span);
- if (waste > (span_size >> 3))
- merge = false;
- }
-
- if (merge) {
- // Adjust last class to include this size
- class_to_size_[sc-1] = size;
- potential_merge_sizes[potential_merge_count++] = size;
- continue;
- }
-
- potential_merge_sizes[0] = size;
- potential_merge_count = 1;
- // Add new class
- class_to_pages_[sc] = my_pages;
- class_to_size_[sc] = size;
- sc++;
- }
-
- if (sc != kNumClasses) {
- Log(kCrash, __FILE__, __LINE__,
- "wrong number of size classes: (found vs. expected )", sc, kNumClasses);
- }
-
- // Initialize the mapping arrays
- int next_size = 0;
- for (int c = 1; c < kNumClasses; c++) {
- const int max_size_in_class = class_to_size_[c];
- for (int s = next_size; s <= max_size_in_class; s += kAlignment) {
- class_array_[ClassIndex(s)] = c;
- }
- next_size = max_size_in_class + kAlignment;
- }
-
- // Double-check sizes just to be safe
- for (size_t size = 0; size <= kMaxSize;) {
- const int sc = SizeClass(size);
- if (sc <= 0 || sc >= kNumClasses) {
- Log(kCrash, __FILE__, __LINE__,
- "Bad size class (class, size)", sc, size);
- }
- if (sc > 1 && size <= class_to_size_[sc-1]) {
- Log(kCrash, __FILE__, __LINE__,
- "Allocating unnecessarily large class (class, size)", sc, size);
- }
- const size_t s = class_to_size_[sc];
- if (size > s || s == 0) {
- Log(kCrash, __FILE__, __LINE__,
- "Bad (class, size, requested)", sc, s, size);
- }
- if (size <= kMaxSmallSize) {
- size += 8;
- } else {
- size += 128;
- }
- }
-
- // Initialize the num_objects_to_move array.
- for (size_t cl = 1; cl < kNumClasses; ++cl) {
- num_objects_to_move_[cl] = NumMoveSize(ByteSizeForClass(cl));
- }
-}
-
-// Metadata allocator -- keeps stats about how many bytes allocated.
-static uint64_t metadata_system_bytes_ = 0;
-static const size_t kMetadataAllocChunkSize = 8*1024*1024;
-// As ThreadCache objects are allocated with MetaDataAlloc, and also
-// CACHELINE_ALIGNED, we must use the same alignment as TCMalloc_SystemAlloc.
-static const size_t kMetadataAllignment = sizeof(MemoryAligner);
-
-static char *metadata_chunk_alloc_;
-static size_t metadata_chunk_avail_;
-
-static SpinLock metadata_alloc_lock(SpinLock::LINKER_INITIALIZED);
-
-void* MetaDataAlloc(size_t bytes) {
- if (bytes >= kMetadataAllocChunkSize) {
- void *rv = TCMalloc_SystemAlloc(bytes,
- NULL, kMetadataAllignment);
- if (rv != NULL) {
- metadata_system_bytes_ += bytes;
- }
- return rv;
- }
-
- SpinLockHolder h(&metadata_alloc_lock);
-
- // the following works by essentially turning address to integer of
- // log_2 kMetadataAllignment size and negating it. I.e. negated
- // value + original value gets 0 and that's what we want modulo
- // kMetadataAllignment. Note, we negate before masking higher bits
- // off, otherwise we'd have to mask them off after negation anyways.
- intptr_t alignment = -reinterpret_cast<intptr_t>(metadata_chunk_alloc_) & (kMetadataAllignment-1);
-
- if (metadata_chunk_avail_ < bytes + alignment) {
- size_t real_size;
- void *ptr = TCMalloc_SystemAlloc(kMetadataAllocChunkSize,
- &real_size, kMetadataAllignment);
- if (ptr == NULL) {
- return NULL;
- }
-
- metadata_chunk_alloc_ = static_cast<char *>(ptr);
- metadata_chunk_avail_ = real_size;
-
- alignment = 0;
- }
-
- void *rv = static_cast<void *>(metadata_chunk_alloc_ + alignment);
- bytes += alignment;
- metadata_chunk_alloc_ += bytes;
- metadata_chunk_avail_ -= bytes;
- metadata_system_bytes_ += bytes;
- return rv;
-}
-
-uint64_t metadata_system_bytes() { return metadata_system_bytes_; }
-
-} // namespace tcmalloc
diff --git a/src/third_party/gperftools-2.5/src/common.h b/src/third_party/gperftools-2.5/src/common.h
deleted file mode 100644
index 2be6bd66866..00000000000
--- a/src/third_party/gperftools-2.5/src/common.h
+++ /dev/null
@@ -1,301 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-//
-// Common definitions for tcmalloc code.
-
-#ifndef TCMALLOC_COMMON_H_
-#define TCMALLOC_COMMON_H_
-
-#include "config.h"
-#include <stddef.h> // for size_t
-#ifdef HAVE_STDINT_H
-#include <stdint.h> // for uintptr_t, uint64_t
-#endif
-#include "internal_logging.h" // for ASSERT, etc
-#include "base/basictypes.h" // for LIKELY, etc
-
-#ifdef HAVE_BUILTIN_EXPECT
-#define LIKELY(x) __builtin_expect(!!(x), 1)
-#define UNLIKELY(x) __builtin_expect(!!(x), 0)
-#else
-#define LIKELY(x) (x)
-#define UNLIKELY(x) (x)
-#endif
-
-// Type that can hold a page number
-typedef uintptr_t PageID;
-
-// Type that can hold the length of a run of pages
-typedef uintptr_t Length;
-
-//-------------------------------------------------------------------
-// Configuration
-//-------------------------------------------------------------------
-
-#if defined(TCMALLOC_ALIGN_8BYTES)
-// Unless we force to use 8 bytes alignment we use an alignment of
-// at least 16 bytes to statisfy requirements for some SSE types.
-// Keep in mind when using the 16 bytes alignment you can have a space
-// waste due alignment of 25%. (eg malloc of 24 bytes will get 32 bytes)
-static const size_t kMinAlign = 8;
-// Number of classes created until reach page size 128.
-static const size_t kBaseClasses = 16;
-#else
-static const size_t kMinAlign = 16;
-static const size_t kBaseClasses = 9;
-#endif
-
-// Using large pages speeds up the execution at a cost of larger memory use.
-// Deallocation may speed up by a factor as the page map gets 8x smaller, so
-// lookups in the page map result in fewer L2 cache misses, which translates to
-// speedup for application/platform combinations with high L2 cache pressure.
-// As the number of size classes increases with large pages, we increase
-// the thread cache allowance to avoid passing more free ranges to and from
-// central lists. Also, larger pages are less likely to get freed.
-// These two factors cause a bounded increase in memory use.
-#if defined(TCMALLOC_32K_PAGES)
-static const size_t kPageShift = 15;
-static const size_t kNumClasses = kBaseClasses + 38;
-#elif defined(TCMALLOC_64K_PAGES)
-static const size_t kPageShift = 16;
-static const size_t kNumClasses = kBaseClasses + 42;
-#else
-static const size_t kPageShift = 12;
-static const size_t kNumClasses = kBaseClasses + 33;
-#endif
-
-static const size_t kMaxThreadCacheSize = 4 << 20;
-
-static const size_t kPageSize = 1 << kPageShift;
-#if defined(TCMALLOC_32K_PAGES)
-static const size_t kMaxSize = 32 * 1024;
-#elif defined(TCMALLOC_64K_PAGES)
-static const size_t kMaxSize = 64 * 1024;
-#else
-static const size_t kMaxSize = 16 * 1024;
-#endif
-static const size_t kAlignment = 8;
-static const size_t kLargeSizeClass = 0;
-// For all span-lengths < kMaxPages we keep an exact-size list.
-static const size_t kMaxPages = 1 << (20 - kPageShift);
-
-// Default bound on the total amount of thread caches.
-#ifdef TCMALLOC_SMALL_BUT_SLOW
-// Make the overall thread cache no bigger than that of a single thread
-// for the small memory footprint case.
-static const size_t kDefaultOverallThreadCacheSize = kMaxThreadCacheSize;
-#else
-static const size_t kDefaultOverallThreadCacheSize = 8u * kMaxThreadCacheSize;
-#endif
-
-// Lower bound on the per-thread cache sizes
-static const size_t kMinThreadCacheSize = kMaxSize * 2;
-
-// The number of bytes one ThreadCache will steal from another when
-// the first ThreadCache is forced to Scavenge(), delaying the
-// next call to Scavenge for this thread.
-static const size_t kStealAmount = 1 << 16;
-
-// The number of times that a deallocation can cause a freelist to
-// go over its max_length() before shrinking max_length().
-static const int kMaxOverages = 3;
-
-// Maximum length we allow a per-thread free-list to have before we
-// move objects from it into the corresponding central free-list. We
-// want this big to avoid locking the central free-list too often. It
-// should not hurt to make this list somewhat big because the
-// scavenging code will shrink it down when its contents are not in use.
-static const int kMaxDynamicFreeListLength = 8192;
-
-static const Length kMaxValidPages = (~static_cast<Length>(0)) >> kPageShift;
-
-#if defined __x86_64__
-// All current and planned x86_64 processors only look at the lower 48 bits
-// in virtual to physical address translation. The top 16 are thus unused.
-// TODO(rus): Under what operating systems can we increase it safely to 17?
-// This lets us use smaller page maps. On first allocation, a 36-bit page map
-// uses only 96 KB instead of the 4.5 MB used by a 52-bit page map.
-static const int kAddressBits = (sizeof(void*) < 8 ? (8 * sizeof(void*)) : 48);
-#else
-static const int kAddressBits = 8 * sizeof(void*);
-#endif
-
-namespace tcmalloc {
-
-// Convert byte size into pages. This won't overflow, but may return
-// an unreasonably large value if bytes is huge enough.
-inline Length pages(size_t bytes) {
- return (bytes >> kPageShift) +
- ((bytes & (kPageSize - 1)) > 0 ? 1 : 0);
-}
-
-// For larger allocation sizes, we use larger memory alignments to
-// reduce the number of size classes.
-int AlignmentForSize(size_t size);
-
-// Size-class information + mapping
-class SizeMap {
- private:
- // Number of objects to move between a per-thread list and a central
- // list in one shot. We want this to be not too small so we can
- // amortize the lock overhead for accessing the central list. Making
- // it too big may temporarily cause unnecessary memory wastage in the
- // per-thread free list until the scavenger cleans up the list.
- int num_objects_to_move_[kNumClasses];
-
- //-------------------------------------------------------------------
- // Mapping from size to size_class and vice versa
- //-------------------------------------------------------------------
-
- // Sizes <= 1024 have an alignment >= 8. So for such sizes we have an
- // array indexed by ceil(size/8). Sizes > 1024 have an alignment >= 128.
- // So for these larger sizes we have an array indexed by ceil(size/128).
- //
- // We flatten both logical arrays into one physical array and use
- // arithmetic to compute an appropriate index. The constants used by
- // ClassIndex() were selected to make the flattening work.
- //
- // Examples:
- // Size Expression Index
- // -------------------------------------------------------
- // 0 (0 + 7) / 8 0
- // 1 (1 + 7) / 8 1
- // ...
- // 1024 (1024 + 7) / 8 128
- // 1025 (1025 + 127 + (120<<7)) / 128 129
- // ...
- // 32768 (32768 + 127 + (120<<7)) / 128 376
- static const int kMaxSmallSize = 1024;
- static const size_t kClassArraySize =
- ((kMaxSize + 127 + (120 << 7)) >> 7) + 1;
- unsigned char class_array_[kClassArraySize];
-
- static inline size_t SmallSizeClass(size_t s) {
- return (static_cast<uint32_t>(s) + 7) >> 3;
- }
-
- static inline size_t LargeSizeClass(size_t s) {
- return (static_cast<uint32_t>(s) + 127 + (120 << 7)) >> 7;
- }
-
- // Compute index of the class_array[] entry for a given size
- static inline size_t ClassIndex(size_t s) {
- // Use unsigned arithmetic to avoid unnecessary sign extensions.
- ASSERT(0 <= s);
- ASSERT(s <= kMaxSize);
- if (LIKELY(s <= kMaxSmallSize)) {
- return SmallSizeClass(s);
- } else {
- return LargeSizeClass(s);
- }
- }
-
- int NumMoveSize(size_t size);
-
- // Mapping from size class to max size storable in that class
- size_t class_to_size_[kNumClasses];
-
- // Mapping from size class to number of pages to allocate at a time
- size_t class_to_pages_[kNumClasses];
-
- public:
- // Constructor should do nothing since we rely on explicit Init()
- // call, which may or may not be called before the constructor runs.
- SizeMap() { }
-
- // Initialize the mapping arrays
- void Init();
-
- inline int SizeClass(size_t size) {
- return class_array_[ClassIndex(size)];
- }
-
- inline bool MaybeSizeClass(size_t size, size_t *size_class) {
- size_t class_idx;
- if (LIKELY(size <= kMaxSmallSize)) {
- class_idx = SmallSizeClass(size);
- } else if (size <= kMaxSize) {
- class_idx = LargeSizeClass(size);
- } else {
- return false;
- }
- *size_class = class_array_[class_idx];
- return true;
- }
-
- // Get the byte-size for a specified class
- inline size_t ByteSizeForClass(size_t cl) {
- return class_to_size_[cl];
- }
-
- // Mapping from size class to max size storable in that class
- inline size_t class_to_size(size_t cl) {
- return class_to_size_[cl];
- }
-
- // Mapping from size class to number of pages to allocate at a time
- inline size_t class_to_pages(size_t cl) {
- return class_to_pages_[cl];
- }
-
- // Number of objects to move between a per-thread list and a central
- // list in one shot. We want this to be not too small so we can
- // amortize the lock overhead for accessing the central list. Making
- // it too big may temporarily cause unnecessary memory wastage in the
- // per-thread free list until the scavenger cleans up the list.
- inline int num_objects_to_move(size_t cl) {
- return num_objects_to_move_[cl];
- }
-};
-
-// Allocates "bytes" worth of memory and returns it. Increments
-// metadata_system_bytes appropriately. May return NULL if allocation
-// fails. Requires pageheap_lock is held.
-void* MetaDataAlloc(size_t bytes);
-
-// Returns the total number of bytes allocated from the system.
-// Requires pageheap_lock is held.
-uint64_t metadata_system_bytes();
-
-// size/depth are made the same size as a pointer so that some generic
-// code below can conveniently cast them back and forth to void*.
-static const int kMaxStackDepth = 31;
-struct StackTrace {
- uintptr_t size; // Size of object
- uintptr_t depth; // Number of PC values stored in array below
- void* stack[kMaxStackDepth];
-};
-
-} // namespace tcmalloc
-
-#endif // TCMALLOC_COMMON_H_
diff --git a/src/third_party/gperftools-2.5/src/config.h.in b/src/third_party/gperftools-2.5/src/config.h.in
deleted file mode 100644
index f7681dabfc4..00000000000
--- a/src/third_party/gperftools-2.5/src/config.h.in
+++ /dev/null
@@ -1,307 +0,0 @@
-/* src/config.h.in. Generated from configure.ac by autoheader. */
-
-
-#ifndef GPERFTOOLS_CONFIG_H_
-#define GPERFTOOLS_CONFIG_H_
-
-
-/* Build runtime detection for sized delete */
-#undef ENABLE_DYNAMIC_SIZED_DELETE
-
-/* Build sized deletion operators */
-#undef ENABLE_SIZED_DELETE
-
-/* Define to 1 if compiler supports __builtin_expect */
-#undef HAVE_BUILTIN_EXPECT
-
-/* Define to 1 if compiler supports __builtin_stack_pointer */
-#undef HAVE_BUILTIN_STACK_POINTER
-
-/* Define to 1 if you have the <conflict-signal.h> header file. */
-#undef HAVE_CONFLICT_SIGNAL_H
-
-/* Define to 1 if you have the <cygwin/signal.h> header file. */
-#undef HAVE_CYGWIN_SIGNAL_H
-
-/* Define to 1 if you have the declaration of `backtrace', and to 0 if you
- don't. */
-#undef HAVE_DECL_BACKTRACE
-
-/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
- */
-#undef HAVE_DECL_CFREE
-
-/* Define to 1 if you have the declaration of `memalign', and to 0 if you
- don't. */
-#undef HAVE_DECL_MEMALIGN
-
-/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you
- don't. */
-#undef HAVE_DECL_NANOSLEEP
-
-/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
- you don't. */
-#undef HAVE_DECL_POSIX_MEMALIGN
-
-/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
- don't. */
-#undef HAVE_DECL_PVALLOC
-
-/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't.
- */
-#undef HAVE_DECL_SLEEP
-
-/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
- */
-#undef HAVE_DECL_UNAME
-
-/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
- */
-#undef HAVE_DECL_VALLOC
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if the system has the type `Elf32_Versym'. */
-#undef HAVE_ELF32_VERSYM
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#undef HAVE_EXECINFO_H
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
-/* Define to 1 if you have the <features.h> header file. */
-#undef HAVE_FEATURES_H
-
-/* Define to 1 if you have the `fork' function. */
-#undef HAVE_FORK
-
-/* Define to 1 if you have the `geteuid' function. */
-#undef HAVE_GETEUID
-
-/* Define to 1 if you have the `getpagesize' function. */
-#undef HAVE_GETPAGESIZE
-
-/* Define to 1 if you have the <glob.h> header file. */
-#undef HAVE_GLOB_H
-
-/* Define to 1 if you have the <grp.h> header file. */
-#undef HAVE_GRP_H
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-#undef HAVE_LIBUNWIND_H
-
-/* Define to 1 if you have the <linux/ptrace.h> header file. */
-#undef HAVE_LINUX_PTRACE_H
-
-/* Define if this is Linux that has SIGEV_THREAD_ID */
-#undef HAVE_LINUX_SIGEV_THREAD_ID
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#undef HAVE_MALLOC_H
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have a working `mmap' system call. */
-#undef HAVE_MMAP
-
-/* define if the compiler implements namespaces */
-#undef HAVE_NAMESPACES
-
-/* Define to 1 if you have the <poll.h> header file. */
-#undef HAVE_POLL_H
-
-/* define if libc has program_invocation_name */
-#undef HAVE_PROGRAM_INVOCATION_NAME
-
-/* Define if you have POSIX threads libraries and header files. */
-#undef HAVE_PTHREAD
-
-/* defined to 1 if pthread symbols are exposed even without include pthread.h
- */
-#undef HAVE_PTHREAD_DESPITE_ASKING_FOR
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#undef HAVE_PWD_H
-
-/* Define to 1 if you have the `sbrk' function. */
-#undef HAVE_SBRK
-
-/* Define to 1 if you have the <sched.h> header file. */
-#undef HAVE_SCHED_H
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* 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/param.h> header file. */
-#undef HAVE_SYS_PARAM_H
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#undef HAVE_SYS_PRCTL_H
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#undef HAVE_SYS_RESOURCE_H
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#undef HAVE_SYS_SOCKET_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#undef HAVE_SYS_SYSCALL_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <sys/ucontext.h> header file. */
-#undef HAVE_SYS_UCONTEXT_H
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#undef HAVE_SYS_WAIT_H
-
-/* Define to 1 if compiler supports __thread */
-#undef HAVE_TLS
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-#undef HAVE_UCONTEXT_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Whether <unwind.h> contains _Unwind_Backtrace */
-#undef HAVE_UNWIND_BACKTRACE
-
-/* Define to 1 if you have the <unwind.h> header file. */
-#undef HAVE_UNWIND_H
-
-/* Define to 1 if you have the <valgrind.h> header file. */
-#undef HAVE_VALGRIND_H
-
-/* define if your compiler has __attribute__ */
-#undef HAVE___ATTRIBUTE__
-
-/* Define to 1 if compiler supports __environ */
-#undef HAVE___ENVIRON
-
-/* Define to 1 if the system has the type `__int64'. */
-#undef HAVE___INT64
-
-/* prefix where we look for installed files */
-#undef INSTALL_PREFIX
-
-/* Define to 1 if int32_t is equivalent to intptr_t */
-#undef INT32_EQUALS_INTPTR
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#undef LT_OBJDIR
-
-/* Define to 'volatile' if __malloc_hook is declared volatile */
-#undef MALLOC_HOOK_MAYBE_VOLATILE
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* How to access the PC from a struct ucontext */
-#undef PC_FROM_UCONTEXT
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#undef PERFTOOLS_DLL_DECL
-
-/* printf format code for printing a size_t and ssize_t */
-#undef PRIdS
-
-/* printf format code for printing a size_t and ssize_t */
-#undef PRIuS
-
-/* 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
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* the namespace where STL code like vector<> is defined */
-#undef STL_NAMESPACE
-
-/* Define 32K of internal pages size for tcmalloc */
-#undef TCMALLOC_32K_PAGES
-
-/* Define 64K of internal pages size for tcmalloc */
-#undef TCMALLOC_64K_PAGES
-
-/* Define 8 bytes of allocation alignment for tcmalloc */
-#undef TCMALLOC_ALIGN_8BYTES
-
-/* Version number of package */
-#undef VERSION
-
-/* C99 says: define this to get the PRI... macros from stdint.h */
-#ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-#undef inline
-#endif
-
-
-#ifdef __MINGW32__
-#include "windows/mingw.h"
-#endif
-
-#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */
-
diff --git a/src/third_party/gperftools-2.5/src/config_for_unittests.h b/src/third_party/gperftools-2.5/src/config_for_unittests.h
deleted file mode 100644
index 66592a70071..00000000000
--- a/src/third_party/gperftools-2.5/src/config_for_unittests.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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.
-
-// ---
-// All Rights Reserved.
-//
-// Author: Craig Silverstein
-//
-// This file is needed for windows -- unittests are not part of the
-// perftools dll, but still want to include config.h just like the
-// dll does, so they can use internal tools and APIs for testing.
-//
-// The problem is that config.h declares PERFTOOLS_DLL_DECL to be
-// for exporting symbols, but the unittest needs to *import* symbols
-// (since it's not the dll).
-//
-// The solution is to have this file, which is just like config.h but
-// sets PERFTOOLS_DLL_DECL to do a dllimport instead of a dllexport.
-//
-// The reason we need this extra PERFTOOLS_DLL_DECL_FOR_UNITTESTS
-// variable is in case people want to set PERFTOOLS_DLL_DECL explicitly
-// to something other than __declspec(dllexport). In that case, they
-// may want to use something other than __declspec(dllimport) for the
-// unittest case. For that, we allow folks to define both
-// PERFTOOLS_DLL_DECL and PERFTOOLS_DLL_DECL_FOR_UNITTESTS explicitly.
-//
-// NOTE: This file is equivalent to config.h on non-windows systems,
-// which never defined PERFTOOLS_DLL_DECL_FOR_UNITTESTS and always
-// define PERFTOOLS_DLL_DECL to the empty string.
-
-#include "config.h"
-
-#undef PERFTOOLS_DLL_DECL
-#ifdef PERFTOOLS_DLL_DECL_FOR_UNITTESTS
-# define PERFTOOLS_DLL_DECL PERFTOOLS_DLL_DECL_FOR_UNITTESTS
-#else
-# define PERFTOOLS_DLL_DECL // if DLL_DECL_FOR_UNITTESTS isn't defined, use ""
-#endif
diff --git a/src/third_party/gperftools-2.5/src/debugallocation.cc b/src/third_party/gperftools-2.5/src/debugallocation.cc
deleted file mode 100644
index 0e650b6483d..00000000000
--- a/src/third_party/gperftools-2.5/src/debugallocation.cc
+++ /dev/null
@@ -1,1490 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2000, 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: Urs Holzle <opensource@google.com>
-
-#include "config.h"
-#include <errno.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-// We only need malloc.h for struct mallinfo.
-#ifdef HAVE_STRUCT_MALLINFO
-// Malloc can be in several places on older versions of OS X.
-# if defined(HAVE_MALLOC_H)
-# include <malloc.h>
-# elif defined(HAVE_MALLOC_MALLOC_H)
-# include <malloc/malloc.h>
-# elif defined(HAVE_SYS_MALLOC_H)
-# include <sys/malloc.h>
-# endif
-#endif
-#ifdef HAVE_PTHREAD
-#include <pthread.h>
-#endif
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <gperftools/malloc_extension.h>
-#include <gperftools/malloc_hook.h>
-#include <gperftools/stacktrace.h>
-#include "addressmap-inl.h"
-#include "base/commandlineflags.h"
-#include "base/googleinit.h"
-#include "base/logging.h"
-#include "base/spinlock.h"
-#include "malloc_hook-inl.h"
-#include "symbolize.h"
-
-// NOTE: due to #define below, tcmalloc.cc will omit tc_XXX
-// definitions. So that debug implementations can be defined
-// instead. We're going to use do_malloc, do_free and other do_XXX
-// functions that are defined in tcmalloc.cc for actual memory
-// management
-#define TCMALLOC_USING_DEBUGALLOCATION
-#include "tcmalloc.cc"
-
-// __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
-
-// 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
-
-// ========================================================================= //
-
-DEFINE_bool(malloctrace,
- EnvToBool("TCMALLOC_TRACE", false),
- "Enables memory (de)allocation tracing to /tmp/google.alloc.");
-#ifdef HAVE_MMAP
-DEFINE_bool(malloc_page_fence,
- EnvToBool("TCMALLOC_PAGE_FENCE", false),
- "Enables putting of memory allocations at page boundaries "
- "with a guard page following the allocation (to catch buffer "
- "overruns right when they happen).");
-DEFINE_bool(malloc_page_fence_never_reclaim,
- EnvToBool("TCMALLOC_PAGE_FRANCE_NEVER_RECLAIM", false),
- "Enables making the virtual address space inaccessible "
- "upon a deallocation instead of returning it and reusing later.");
-#else
-DEFINE_bool(malloc_page_fence, false, "Not usable (requires mmap)");
-DEFINE_bool(malloc_page_fence_never_reclaim, false, "Not usable (required mmap)");
-#endif
-DEFINE_bool(malloc_reclaim_memory,
- EnvToBool("TCMALLOC_RECLAIM_MEMORY", true),
- "If set to false, we never return memory to malloc "
- "when an object is deallocated. This ensures that all "
- "heap object addresses are unique.");
-DEFINE_int32(max_free_queue_size,
- EnvToInt("TCMALLOC_MAX_FREE_QUEUE_SIZE", 10*1024*1024),
- "If greater than 0, keep freed blocks in a queue instead of "
- "releasing them to the allocator immediately. Release them when "
- "the total size of all blocks in the queue would otherwise exceed "
- "this limit.");
-
-DEFINE_bool(symbolize_stacktrace,
- EnvToBool("TCMALLOC_SYMBOLIZE_STACKTRACE", true),
- "Symbolize the stack trace when provided (on some error exits)");
-
-// If we are LD_PRELOAD-ed against a non-pthreads app, then
-// pthread_once won't be defined. We declare it here, for that
-// case (with weak linkage) which will cause the non-definition to
-// resolve to NULL. We can then check for NULL or not in Instance.
-extern "C" int pthread_once(pthread_once_t *, void (*)(void))
- ATTRIBUTE_WEAK;
-
-// ========================================================================= //
-
-// A safe version of printf() that does not do any allocation and
-// uses very little stack space.
-static void TracePrintf(int fd, const char *fmt, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));
-
-// Round "value" up to next "alignment" boundary.
-// Requires that "alignment" be a power of two.
-static intptr_t RoundUp(intptr_t value, intptr_t alignment) {
- return (value + alignment - 1) & ~(alignment - 1);
-}
-
-// ========================================================================= //
-
-class MallocBlock;
-
-// A circular buffer to hold freed blocks of memory. MallocBlock::Deallocate
-// (below) pushes blocks into this queue instead of returning them to the
-// underlying allocator immediately. See MallocBlock::Deallocate for more
-// information.
-//
-// We can't use an STL class for this because we need to be careful not to
-// perform any heap de-allocations in any of the code in this class, since the
-// code in MallocBlock::Deallocate is not re-entrant.
-template <typename QueueEntry>
-class FreeQueue {
- public:
- FreeQueue() : q_front_(0), q_back_(0) {}
-
- bool Full() {
- return (q_front_ + 1) % kFreeQueueSize == q_back_;
- }
-
- void Push(const QueueEntry& block) {
- q_[q_front_] = block;
- q_front_ = (q_front_ + 1) % kFreeQueueSize;
- }
-
- QueueEntry Pop() {
- RAW_CHECK(q_back_ != q_front_, "Queue is empty");
- const QueueEntry& ret = q_[q_back_];
- q_back_ = (q_back_ + 1) % kFreeQueueSize;
- return ret;
- }
-
- size_t size() const {
- return (q_front_ - q_back_ + kFreeQueueSize) % kFreeQueueSize;
- }
-
- private:
- // Maximum number of blocks kept in the free queue before being freed.
- static const int kFreeQueueSize = 1024;
-
- QueueEntry q_[kFreeQueueSize];
- int q_front_;
- int q_back_;
-};
-
-struct MallocBlockQueueEntry {
- MallocBlockQueueEntry() : block(NULL), size(0),
- num_deleter_pcs(0), deleter_threadid(0) {}
- MallocBlockQueueEntry(MallocBlock* b, size_t s) : block(b), size(s) {
- if (FLAGS_max_free_queue_size != 0 && b != NULL) {
- // Adjust the number of frames to skip (4) if you change the
- // location of this call.
- num_deleter_pcs =
- GetStackTrace(deleter_pcs,
- sizeof(deleter_pcs) / sizeof(deleter_pcs[0]),
- 4);
- deleter_threadid = pthread_self();
- } else {
- num_deleter_pcs = 0;
- // Zero is an illegal pthread id by my reading of the pthread
- // implementation:
- deleter_threadid = 0;
- }
- }
-
- MallocBlock* block;
- size_t size;
-
- // When deleted and put in the free queue, we (flag-controlled)
- // record the stack so that if corruption is later found, we can
- // print the deleter's stack. (These three vars add 144 bytes of
- // overhead under the LP64 data model.)
- void* deleter_pcs[16];
- int num_deleter_pcs;
- pthread_t deleter_threadid;
-};
-
-class MallocBlock {
- public: // allocation type constants
-
- // Different allocation types we distinguish.
- // Note: The lower 4 bits are not random: we index kAllocName array
- // by these values masked with kAllocTypeMask;
- // the rest are "random" magic bits to help catch memory corruption.
- static const int kMallocType = 0xEFCDAB90;
- static const int kNewType = 0xFEBADC81;
- static const int kArrayNewType = 0xBCEADF72;
-
- private: // constants
-
- // A mask used on alloc types above to get to 0, 1, 2
- static const int kAllocTypeMask = 0x3;
- // An additional bit to set in AllocType constants
- // to mark now deallocated regions.
- static const int kDeallocatedTypeBit = 0x4;
-
- // For better memory debugging, we initialize all storage to known
- // values, and overwrite the storage when it's deallocated:
- // Byte that fills uninitialized storage.
- static const int kMagicUninitializedByte = 0xAB;
- // Byte that fills deallocated storage.
- // NOTE: tcmalloc.cc depends on the value of kMagicDeletedByte
- // to work around a bug in the pthread library.
- static const int kMagicDeletedByte = 0xCD;
- // A size_t (type of alloc_type_ below) in a deallocated storage
- // filled with kMagicDeletedByte.
- static const size_t kMagicDeletedSizeT =
- 0xCDCDCDCD | (((size_t)0xCDCDCDCD << 16) << 16);
- // Initializer works for 32 and 64 bit size_ts;
- // "<< 16 << 16" is to fool gcc from issuing a warning
- // when size_ts are 32 bits.
-
- // NOTE: on Linux, you can enable malloc debugging support in libc by
- // setting the environment variable MALLOC_CHECK_ to 1 before you
- // start the program (see man malloc).
-
- // We use either do_malloc or mmap to make the actual allocation. In
- // order to remember which one of the two was used for any block, we store an
- // appropriate magic word next to the block.
- static const int kMagicMalloc = 0xDEADBEEF;
- static const int kMagicMMap = 0xABCDEFAB;
-
- // This array will be filled with 0xCD, for use with memcmp.
- static unsigned char kMagicDeletedBuffer[1024];
- static pthread_once_t deleted_buffer_initialized_;
- static bool deleted_buffer_initialized_no_pthreads_;
-
- private: // data layout
-
- // The four fields size1_,offset_,magic1_,alloc_type_
- // should together occupy a multiple of 16 bytes. (At the
- // moment, sizeof(size_t) == 4 or 8 depending on piii vs
- // k8, and 4 of those sum to 16 or 32 bytes).
- // This, combined with do_malloc's alignment guarantees,
- // ensures that SSE types can be stored into the returned
- // block, at &size2_.
- size_t size1_;
- size_t offset_; // normally 0 unless memaligned memory
- // see comments in memalign() and FromRawPointer().
- size_t magic1_;
- size_t alloc_type_;
- // here comes the actual data (variable length)
- // ...
- // then come the size2_ and magic2_, or a full page of mprotect-ed memory
- // if the malloc_page_fence feature is enabled.
- size_t size2_;
- int magic2_;
-
- private: // static data and helpers
-
- // Allocation map: stores the allocation type for each allocated object,
- // or the type or'ed with kDeallocatedTypeBit
- // for each formerly allocated object.
- typedef AddressMap<int> AllocMap;
- static AllocMap* alloc_map_;
- // This protects alloc_map_ and consistent state of metadata
- // for each still-allocated object in it.
- // We use spin locks instead of pthread_mutex_t locks
- // to prevent crashes via calls to pthread_mutex_(un)lock
- // for the (de)allocations coming from pthreads initialization itself.
- static SpinLock alloc_map_lock_;
-
- // A queue of freed blocks. Instead of releasing blocks to the allocator
- // immediately, we put them in a queue, freeing them only when necessary
- // to keep the total size of all the freed blocks below the limit set by
- // FLAGS_max_free_queue_size.
- static FreeQueue<MallocBlockQueueEntry>* free_queue_;
-
- static size_t free_queue_size_; // total size of blocks in free_queue_
- // protects free_queue_ and free_queue_size_
- static SpinLock free_queue_lock_;
-
- // Names of allocation types (kMallocType, kNewType, kArrayNewType)
- static const char* const kAllocName[];
- // Names of corresponding deallocation types
- static const char* const kDeallocName[];
-
- static const char* AllocName(int type) {
- return kAllocName[type & kAllocTypeMask];
- }
-
- static const char* DeallocName(int type) {
- return kDeallocName[type & kAllocTypeMask];
- }
-
- private: // helper accessors
-
- bool IsMMapped() const { return kMagicMMap == magic1_; }
-
- bool IsValidMagicValue(int value) const {
- return kMagicMMap == value || kMagicMalloc == value;
- }
-
- static size_t real_malloced_size(size_t size) {
- return size + sizeof(MallocBlock);
- }
-
- /*
- * Here we assume size of page is kMinAlign aligned,
- * so if size is MALLOC_ALIGNMENT aligned too, then we could
- * guarantee return address is also kMinAlign aligned, because
- * mmap return address at nearby page boundary on Linux.
- */
- static size_t real_mmapped_size(size_t size) {
- size_t tmp = size + MallocBlock::data_offset();
- tmp = RoundUp(tmp, kMinAlign);
- return tmp;
- }
-
- size_t real_size() {
- return IsMMapped() ? real_mmapped_size(size1_) : real_malloced_size(size1_);
- }
-
- // NOTE: if the block is mmapped (that is, we're using the
- // malloc_page_fence option) then there's no size2 or magic2
- // (instead, the guard page begins where size2 would be).
-
- size_t* size2_addr() { return (size_t*)((char*)&size2_ + size1_); }
- const size_t* size2_addr() const {
- return (const size_t*)((char*)&size2_ + size1_);
- }
-
- int* magic2_addr() { return (int*)(size2_addr() + 1); }
- const int* magic2_addr() const { return (const int*)(size2_addr() + 1); }
-
- private: // other helpers
-
- void Initialize(size_t size, int type) {
- RAW_CHECK(IsValidMagicValue(magic1_), "");
- // record us as allocated in the map
- alloc_map_lock_.Lock();
- if (!alloc_map_) {
- void* p = do_malloc(sizeof(AllocMap));
- alloc_map_ = new(p) AllocMap(do_malloc, do_free);
- }
- alloc_map_->Insert(data_addr(), type);
- // initialize us
- size1_ = size;
- offset_ = 0;
- alloc_type_ = type;
- if (!IsMMapped()) {
- *magic2_addr() = magic1_;
- *size2_addr() = size;
- }
- alloc_map_lock_.Unlock();
- memset(data_addr(), kMagicUninitializedByte, size);
- if (!IsMMapped()) {
- RAW_CHECK(size1_ == *size2_addr(), "should hold");
- RAW_CHECK(magic1_ == *magic2_addr(), "should hold");
- }
- }
-
- size_t CheckAndClear(int type, size_t given_size) {
- alloc_map_lock_.Lock();
- CheckLocked(type);
- if (!IsMMapped()) {
- RAW_CHECK(size1_ == *size2_addr(), "should hold");
- }
- // record us as deallocated in the map
- alloc_map_->Insert(data_addr(), type | kDeallocatedTypeBit);
- alloc_map_lock_.Unlock();
- // clear us
- const size_t size = real_size();
- RAW_CHECK(!given_size || given_size == size1_,
- "right size must be passed to sized delete");
- memset(this, kMagicDeletedByte, size);
- return size;
- }
-
- void CheckLocked(int type) const {
- int map_type = 0;
- const int* found_type =
- alloc_map_ != NULL ? alloc_map_->Find(data_addr()) : NULL;
- if (found_type == NULL) {
- RAW_LOG(FATAL, "memory allocation bug: object at %p "
- "has never been allocated", data_addr());
- } else {
- map_type = *found_type;
- }
- if ((map_type & kDeallocatedTypeBit) != 0) {
- RAW_LOG(FATAL, "memory allocation bug: object at %p "
- "has been already deallocated (it was allocated with %s)",
- data_addr(), AllocName(map_type & ~kDeallocatedTypeBit));
- }
- if (alloc_type_ == kMagicDeletedSizeT) {
- RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
- "has been corrupted; or else the object has been already "
- "deallocated and our memory map has been corrupted",
- data_addr());
- }
- if (!IsValidMagicValue(magic1_)) {
- RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
- "has been corrupted; "
- "or else our memory map has been corrupted and this is a "
- "deallocation for not (currently) heap-allocated object",
- data_addr());
- }
- if (!IsMMapped()) {
- if (size1_ != *size2_addr()) {
- RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
- "has been corrupted", data_addr());
- }
- if (!IsValidMagicValue(*magic2_addr())) {
- RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
- "has been corrupted", data_addr());
- }
- }
- if (alloc_type_ != type) {
- if ((alloc_type_ != MallocBlock::kMallocType) &&
- (alloc_type_ != MallocBlock::kNewType) &&
- (alloc_type_ != MallocBlock::kArrayNewType)) {
- RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
- "has been corrupted", data_addr());
- }
- RAW_LOG(FATAL, "memory allocation/deallocation mismatch at %p: "
- "allocated with %s being deallocated with %s",
- data_addr(), AllocName(alloc_type_), DeallocName(type));
- }
- if (alloc_type_ != map_type) {
- RAW_LOG(FATAL, "memory stomping bug: our memory map has been corrupted : "
- "allocation at %p made with %s "
- "is recorded in the map to be made with %s",
- data_addr(), AllocName(alloc_type_), AllocName(map_type));
- }
- }
-
- public: // public accessors
-
- void* data_addr() { return (void*)&size2_; }
- const void* data_addr() const { return (const void*)&size2_; }
-
- static size_t data_offset() { return OFFSETOF_MEMBER(MallocBlock, size2_); }
-
- size_t data_size() const { return size1_; }
-
- void set_offset(int offset) { this->offset_ = offset; }
-
- public: // our main interface
-
- static MallocBlock* Allocate(size_t size, int type) {
- // Prevent an integer overflow / crash with large allocation sizes.
- // TODO - Note that for a e.g. 64-bit size_t, max_size_t may not actually
- // be the maximum value, depending on how the compiler treats ~0. The worst
- // practical effect is that allocations are limited to 4Gb or so, even if
- // the address space could take more.
- static size_t max_size_t = ~0;
- if (size > max_size_t - sizeof(MallocBlock)) {
- RAW_LOG(ERROR, "Massive size passed to malloc: %" PRIuS "", size);
- return NULL;
- }
- MallocBlock* b = NULL;
- const bool use_malloc_page_fence = FLAGS_malloc_page_fence;
-#ifdef HAVE_MMAP
- if (use_malloc_page_fence) {
- // Put the block towards the end of the page and make the next page
- // inaccessible. This will catch buffer overrun right when it happens.
- size_t sz = real_mmapped_size(size);
- int pagesize = getpagesize();
- int num_pages = (sz + pagesize - 1) / pagesize + 1;
- char* p = (char*) mmap(NULL, num_pages * pagesize, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- if (p == MAP_FAILED) {
- // If the allocation fails, abort rather than returning NULL to
- // malloc. This is because in most cases, the program will run out
- // of memory in this mode due to tremendous amount of wastage. There
- // is no point in propagating the error elsewhere.
- RAW_LOG(FATAL, "Out of memory: possibly due to page fence overhead: %s",
- strerror(errno));
- }
- // Mark the page after the block inaccessible
- if (mprotect(p + (num_pages - 1) * pagesize, pagesize, PROT_NONE)) {
- RAW_LOG(FATAL, "Guard page setup failed: %s", strerror(errno));
- }
- b = (MallocBlock*) (p + (num_pages - 1) * pagesize - sz);
- } else {
- b = (MallocBlock*) do_malloc(real_malloced_size(size));
- }
-#else
- b = (MallocBlock*) do_malloc(real_malloced_size(size));
-#endif
-
- // It would be nice to output a diagnostic on allocation failure
- // here, but logging (other than FATAL) requires allocating
- // memory, which could trigger a nasty recursion. Instead, preserve
- // malloc semantics and return NULL on failure.
- if (b != NULL) {
- b->magic1_ = use_malloc_page_fence ? kMagicMMap : kMagicMalloc;
- b->Initialize(size, type);
- }
- return b;
- }
-
- void Deallocate(int type, size_t given_size) {
- if (IsMMapped()) { // have to do this before CheckAndClear
-#ifdef HAVE_MMAP
- int size = CheckAndClear(type, given_size);
- int pagesize = getpagesize();
- int num_pages = (size + pagesize - 1) / pagesize + 1;
- char* p = (char*) this;
- if (FLAGS_malloc_page_fence_never_reclaim ||
- !FLAGS_malloc_reclaim_memory) {
- mprotect(p - (num_pages - 1) * pagesize + size,
- num_pages * pagesize, PROT_NONE);
- } else {
- munmap(p - (num_pages - 1) * pagesize + size, num_pages * pagesize);
- }
-#endif
- } else {
- const size_t size = CheckAndClear(type, given_size);
- if (FLAGS_malloc_reclaim_memory) {
- // Instead of freeing the block immediately, push it onto a queue of
- // recently freed blocks. Free only enough blocks to keep from
- // exceeding the capacity of the queue or causing the total amount of
- // un-released memory in the queue from exceeding
- // FLAGS_max_free_queue_size.
- ProcessFreeQueue(this, size, FLAGS_max_free_queue_size);
- }
- }
- }
-
- static size_t FreeQueueSize() {
- SpinLockHolder l(&free_queue_lock_);
- return free_queue_size_;
- }
-
- static void ProcessFreeQueue(MallocBlock* b, size_t size,
- int max_free_queue_size) {
- // MallocBlockQueueEntry are about 144 in size, so we can only
- // use a small array of them on the stack.
- MallocBlockQueueEntry entries[4];
- int num_entries = 0;
- MallocBlockQueueEntry new_entry(b, size);
- free_queue_lock_.Lock();
- if (free_queue_ == NULL)
- free_queue_ = new FreeQueue<MallocBlockQueueEntry>;
- RAW_CHECK(!free_queue_->Full(), "Free queue mustn't be full!");
-
- if (b != NULL) {
- free_queue_size_ += size + sizeof(MallocBlockQueueEntry);
- free_queue_->Push(new_entry);
- }
-
- // Free blocks until the total size of unfreed blocks no longer exceeds
- // max_free_queue_size, and the free queue has at least one free
- // space in it.
- while (free_queue_size_ > max_free_queue_size || free_queue_->Full()) {
- RAW_CHECK(num_entries < arraysize(entries), "entries array overflow");
- entries[num_entries] = free_queue_->Pop();
- free_queue_size_ -=
- entries[num_entries].size + sizeof(MallocBlockQueueEntry);
- num_entries++;
- if (num_entries == arraysize(entries)) {
- // The queue will not be full at this point, so it is ok to
- // release the lock. The queue may still contain more than
- // max_free_queue_size, but this is not a strict invariant.
- free_queue_lock_.Unlock();
- for (int i = 0; i < num_entries; i++) {
- CheckForDanglingWrites(entries[i]);
- do_free(entries[i].block);
- }
- num_entries = 0;
- free_queue_lock_.Lock();
- }
- }
- RAW_CHECK(free_queue_size_ >= 0, "Free queue size went negative!");
- free_queue_lock_.Unlock();
- for (int i = 0; i < num_entries; i++) {
- CheckForDanglingWrites(entries[i]);
- do_free(entries[i].block);
- }
- }
-
- static void InitDeletedBuffer() {
- memset(kMagicDeletedBuffer, kMagicDeletedByte, sizeof(kMagicDeletedBuffer));
- deleted_buffer_initialized_no_pthreads_ = true;
- }
-
- static void CheckForDanglingWrites(const MallocBlockQueueEntry& queue_entry) {
- // Initialize the buffer if necessary.
- if (pthread_once)
- pthread_once(&deleted_buffer_initialized_, &InitDeletedBuffer);
- if (!deleted_buffer_initialized_no_pthreads_) {
- // This will be the case on systems that don't link in pthreads,
- // including on FreeBSD where pthread_once has a non-zero address
- // (but doesn't do anything) even when pthreads isn't linked in.
- InitDeletedBuffer();
- }
-
- const unsigned char* p =
- reinterpret_cast<unsigned char*>(queue_entry.block);
-
- static const size_t size_of_buffer = sizeof(kMagicDeletedBuffer);
- const size_t size = queue_entry.size;
- const size_t buffers = size / size_of_buffer;
- const size_t remainder = size % size_of_buffer;
- size_t buffer_idx;
- for (buffer_idx = 0; buffer_idx < buffers; ++buffer_idx) {
- CheckForCorruptedBuffer(queue_entry, buffer_idx, p, size_of_buffer);
- p += size_of_buffer;
- }
- CheckForCorruptedBuffer(queue_entry, buffer_idx, p, remainder);
- }
-
- static void CheckForCorruptedBuffer(const MallocBlockQueueEntry& queue_entry,
- size_t buffer_idx,
- const unsigned char* buffer,
- size_t size_of_buffer) {
- if (memcmp(buffer, kMagicDeletedBuffer, size_of_buffer) == 0) {
- return;
- }
-
- RAW_LOG(ERROR,
- "Found a corrupted memory buffer in MallocBlock (may be offset "
- "from user ptr): buffer index: %zd, buffer ptr: %p, size of "
- "buffer: %zd", buffer_idx, buffer, size_of_buffer);
-
- // The magic deleted buffer should only be 1024 bytes, but in case
- // this changes, let's put an upper limit on the number of debug
- // lines we'll output:
- if (size_of_buffer <= 1024) {
- for (int i = 0; i < size_of_buffer; ++i) {
- if (buffer[i] != kMagicDeletedByte) {
- RAW_LOG(ERROR, "Buffer byte %d is 0x%02x (should be 0x%02x).",
- i, buffer[i], kMagicDeletedByte);
- }
- }
- } else {
- RAW_LOG(ERROR, "Buffer too large to print corruption.");
- }
-
- const MallocBlock* b = queue_entry.block;
- const size_t size = queue_entry.size;
- if (queue_entry.num_deleter_pcs > 0) {
- TracePrintf(STDERR_FILENO, "Deleted by thread %p\n",
- reinterpret_cast<void*>(
- PRINTABLE_PTHREAD(queue_entry.deleter_threadid)));
-
- // We don't want to allocate or deallocate memory here, so we use
- // placement-new. It's ok that we don't destroy this, since we're
- // just going to error-exit below anyway. Union is for alignment.
- union { void* alignment; char buf[sizeof(SymbolTable)]; } tablebuf;
- SymbolTable* symbolization_table = new (tablebuf.buf) SymbolTable;
- for (int i = 0; i < queue_entry.num_deleter_pcs; i++) {
- // Symbolizes the previous address of pc because pc may be in the
- // next function. This may happen when the function ends with
- // a call to a function annotated noreturn (e.g. CHECK).
- char *pc = reinterpret_cast<char*>(queue_entry.deleter_pcs[i]);
- symbolization_table->Add(pc - 1);
- }
- if (FLAGS_symbolize_stacktrace)
- symbolization_table->Symbolize();
- for (int i = 0; i < queue_entry.num_deleter_pcs; i++) {
- char *pc = reinterpret_cast<char*>(queue_entry.deleter_pcs[i]);
- TracePrintf(STDERR_FILENO, " @ %p %s\n",
- pc, symbolization_table->GetSymbol(pc - 1));
- }
- } else {
- RAW_LOG(ERROR,
- "Skipping the printing of the deleter's stack! Its stack was "
- "not found; either the corruption occurred too early in "
- "execution to obtain a stack trace or --max_free_queue_size was "
- "set to 0.");
- }
-
- RAW_LOG(FATAL,
- "Memory was written to after being freed. MallocBlock: %p, user "
- "ptr: %p, size: %zd. If you can't find the source of the error, "
- "try using ASan (http://code.google.com/p/address-sanitizer/), "
- "Valgrind, or Purify, or study the "
- "output of the deleter's stack printed above.",
- b, b->data_addr(), size);
- }
-
- static MallocBlock* FromRawPointer(void* p) {
- const size_t data_offset = MallocBlock::data_offset();
- // Find the header just before client's memory.
- MallocBlock *mb = reinterpret_cast<MallocBlock *>(
- reinterpret_cast<char *>(p) - data_offset);
- // If mb->alloc_type_ is kMagicDeletedSizeT, we're not an ok pointer.
- if (mb->alloc_type_ == kMagicDeletedSizeT) {
- RAW_LOG(FATAL, "memory allocation bug: object at %p has been already"
- " deallocated; or else a word before the object has been"
- " corrupted (memory stomping bug)", p);
- }
- // If mb->offset_ is zero (common case), mb is the real header.
- // If mb->offset_ is non-zero, this block was allocated by debug
- // memallign implementation, and mb->offset_ is the distance
- // backwards to the real header from mb, which is a fake header.
- if (mb->offset_ == 0) {
- return mb;
- }
-
- MallocBlock *main_block = reinterpret_cast<MallocBlock *>(
- reinterpret_cast<char *>(mb) - mb->offset_);
-
- if (main_block->offset_ != 0) {
- RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted."
- " Need 0 but got %x",
- (unsigned)(main_block->offset_));
- }
- if (main_block >= p) {
- RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted."
- " Detected main_block address overflow: %x",
- (unsigned)(mb->offset_));
- }
- if (main_block->size2_addr() < p) {
- RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted."
- " It points below it's own main_block: %x",
- (unsigned)(mb->offset_));
- }
-
- return main_block;
- }
-
- static const MallocBlock* FromRawPointer(const void* p) {
- // const-safe version: we just cast about
- return FromRawPointer(const_cast<void*>(p));
- }
-
- void Check(int type) const {
- alloc_map_lock_.Lock();
- CheckLocked(type);
- alloc_map_lock_.Unlock();
- }
-
- static bool CheckEverything() {
- alloc_map_lock_.Lock();
- if (alloc_map_ != NULL) alloc_map_->Iterate(CheckCallback, 0);
- alloc_map_lock_.Unlock();
- return true; // if we get here, we're okay
- }
-
- static bool MemoryStats(int* blocks, size_t* total,
- int histogram[kMallocHistogramSize]) {
- memset(histogram, 0, kMallocHistogramSize * sizeof(int));
- alloc_map_lock_.Lock();
- stats_blocks_ = 0;
- stats_total_ = 0;
- stats_histogram_ = histogram;
- if (alloc_map_ != NULL) alloc_map_->Iterate(StatsCallback, 0);
- *blocks = stats_blocks_;
- *total = stats_total_;
- alloc_map_lock_.Unlock();
- return true;
- }
-
- private: // helpers for CheckEverything and MemoryStats
-
- static void CheckCallback(const void* ptr, int* type, int dummy) {
- if ((*type & kDeallocatedTypeBit) == 0) {
- FromRawPointer(ptr)->CheckLocked(*type);
- }
- }
-
- // Accumulation variables for StatsCallback protected by alloc_map_lock_
- static int stats_blocks_;
- static size_t stats_total_;
- static int* stats_histogram_;
-
- static void StatsCallback(const void* ptr, int* type, int dummy) {
- if ((*type & kDeallocatedTypeBit) == 0) {
- const MallocBlock* b = FromRawPointer(ptr);
- b->CheckLocked(*type);
- ++stats_blocks_;
- size_t mysize = b->size1_;
- int entry = 0;
- stats_total_ += mysize;
- while (mysize) {
- ++entry;
- mysize >>= 1;
- }
- RAW_CHECK(entry < kMallocHistogramSize,
- "kMallocHistogramSize should be at least as large as log2 "
- "of the maximum process memory size");
- stats_histogram_[entry] += 1;
- }
- }
-};
-
-void DanglingWriteChecker() {
- // Clear out the remaining free queue to check for dangling writes.
- MallocBlock::ProcessFreeQueue(NULL, 0, 0);
-}
-
-// ========================================================================= //
-
-const int MallocBlock::kMagicMalloc;
-const int MallocBlock::kMagicMMap;
-
-MallocBlock::AllocMap* MallocBlock::alloc_map_ = NULL;
-SpinLock MallocBlock::alloc_map_lock_(SpinLock::LINKER_INITIALIZED);
-
-FreeQueue<MallocBlockQueueEntry>* MallocBlock::free_queue_ = NULL;
-size_t MallocBlock::free_queue_size_ = 0;
-SpinLock MallocBlock::free_queue_lock_(SpinLock::LINKER_INITIALIZED);
-
-unsigned char MallocBlock::kMagicDeletedBuffer[1024];
-pthread_once_t MallocBlock::deleted_buffer_initialized_ = PTHREAD_ONCE_INIT;
-bool MallocBlock::deleted_buffer_initialized_no_pthreads_ = false;
-
-const char* const MallocBlock::kAllocName[] = {
- "malloc",
- "new",
- "new []",
- NULL,
-};
-
-const char* const MallocBlock::kDeallocName[] = {
- "free",
- "delete",
- "delete []",
- NULL,
-};
-
-int MallocBlock::stats_blocks_;
-size_t MallocBlock::stats_total_;
-int* MallocBlock::stats_histogram_;
-
-// ========================================================================= //
-
-// The following cut-down version of printf() avoids
-// using stdio or ostreams.
-// This is to guarantee no recursive calls into
-// the allocator and to bound the stack space consumed. (The pthread
-// manager thread in linuxthreads has a very small stack,
-// so fprintf can't be called.)
-static void TracePrintf(int fd, const char *fmt, ...) {
- char buf[64];
- int i = 0;
- va_list ap;
- va_start(ap, fmt);
- const char *p = fmt;
- char numbuf[25];
- if (fd < 0) {
- return;
- }
- numbuf[sizeof(numbuf)-1] = 0;
- while (*p != '\0') { // until end of format string
- char *s = &numbuf[sizeof(numbuf)-1];
- if (p[0] == '%' && p[1] != 0) { // handle % formats
- int64 l = 0;
- unsigned long base = 0;
- if (*++p == 's') { // %s
- s = va_arg(ap, char *);
- } else if (*p == 'l' && p[1] == 'd') { // %ld
- l = va_arg(ap, long);
- base = 10;
- p++;
- } else if (*p == 'l' && p[1] == 'u') { // %lu
- l = va_arg(ap, unsigned long);
- base = 10;
- p++;
- } else if (*p == 'z' && p[1] == 'u') { // %zu
- l = va_arg(ap, size_t);
- base = 10;
- p++;
- } else if (*p == 'u') { // %u
- l = va_arg(ap, unsigned int);
- base = 10;
- } else if (*p == 'd') { // %d
- l = va_arg(ap, int);
- base = 10;
- } else if (*p == 'p') { // %p
- l = va_arg(ap, intptr_t);
- base = 16;
- } else {
- write(STDERR_FILENO, "Unimplemented TracePrintf format\n", 33);
- write(STDERR_FILENO, p, 2);
- write(STDERR_FILENO, "\n", 1);
- abort();
- }
- p++;
- if (base != 0) {
- bool minus = (l < 0 && base == 10);
- uint64 ul = minus? -l : l;
- do {
- *--s = "0123456789abcdef"[ul % base];
- ul /= base;
- } while (ul != 0);
- if (base == 16) {
- *--s = 'x';
- *--s = '0';
- } else if (minus) {
- *--s = '-';
- }
- }
- } else { // handle normal characters
- *--s = *p++;
- }
- while (*s != 0) {
- if (i == sizeof(buf)) {
- write(fd, buf, i);
- i = 0;
- }
- buf[i++] = *s++;
- }
- }
- if (i != 0) {
- write(fd, buf, i);
- }
- va_end(ap);
-}
-
-// Return the file descriptor we're writing a log to
-static int TraceFd() {
- static int trace_fd = -1;
- if (trace_fd == -1) { // Open the trace file on the first call
- const char *val = getenv("TCMALLOC_TRACE_FILE");
- bool fallback_to_stderr = false;
- if (!val) {
- val = "/tmp/google.alloc";
- fallback_to_stderr = true;
- }
- trace_fd = open(val, O_CREAT|O_TRUNC|O_WRONLY, 0666);
- if (trace_fd == -1) {
- if (fallback_to_stderr) {
- trace_fd = 2;
- TracePrintf(trace_fd, "Can't open %s. Logging to stderr.\n", val);
- } else {
- TracePrintf(2, "Can't open %s. Logging disabled.\n", val);
- }
- }
- // Add a header to the log.
- TracePrintf(trace_fd, "Trace started: %lu\n",
- static_cast<unsigned long>(time(NULL)));
- TracePrintf(trace_fd,
- "func\tsize\tptr\tthread_id\tstack pcs for tools/symbolize\n");
- }
- return trace_fd;
-}
-
-// Print the hex stack dump on a single line. PCs are separated by tabs.
-static void TraceStack(void) {
- void *pcs[16];
- int n = GetStackTrace(pcs, sizeof(pcs)/sizeof(pcs[0]), 0);
- for (int i = 0; i != n; i++) {
- TracePrintf(TraceFd(), "\t%p", pcs[i]);
- }
-}
-
-// This protects MALLOC_TRACE, to make sure its info is atomically written.
-static SpinLock malloc_trace_lock(SpinLock::LINKER_INITIALIZED);
-
-#define MALLOC_TRACE(name, size, addr) \
- do { \
- if (FLAGS_malloctrace) { \
- SpinLockHolder l(&malloc_trace_lock); \
- TracePrintf(TraceFd(), "%s\t%" PRIuS "\t%p\t%" GPRIuPTHREAD, \
- name, size, addr, PRINTABLE_PTHREAD(pthread_self())); \
- TraceStack(); \
- TracePrintf(TraceFd(), "\n"); \
- } \
- } while (0)
-
-// ========================================================================= //
-
-// Write the characters buf[0, ..., size-1] to
-// the malloc trace buffer.
-// This function is intended for debugging,
-// and is not declared in any header file.
-// You must insert a declaration of it by hand when you need
-// to use it.
-void __malloctrace_write(const char *buf, size_t size) {
- if (FLAGS_malloctrace) {
- write(TraceFd(), buf, size);
- }
-}
-
-// ========================================================================= //
-
-// General debug allocation/deallocation
-
-static inline void* DebugAllocate(size_t size, int type) {
- MallocBlock* ptr = MallocBlock::Allocate(size, type);
- if (ptr == NULL) return NULL;
- MALLOC_TRACE("malloc", size, ptr->data_addr());
- return ptr->data_addr();
-}
-
-static inline void DebugDeallocate(void* ptr, int type, size_t given_size) {
- MALLOC_TRACE("free",
- (ptr != 0 ? MallocBlock::FromRawPointer(ptr)->data_size() : 0),
- ptr);
- if (ptr) MallocBlock::FromRawPointer(ptr)->Deallocate(type, given_size);
-}
-
-// ========================================================================= //
-
-// The following functions may be called via MallocExtension::instance()
-// for memory verification and statistics.
-class DebugMallocImplementation : public TCMallocImplementation {
- public:
- virtual bool GetNumericProperty(const char* name, size_t* value) {
- bool result = TCMallocImplementation::GetNumericProperty(name, value);
- if (result && (strcmp(name, "generic.current_allocated_bytes") == 0)) {
- // Subtract bytes kept in the free queue
- size_t qsize = MallocBlock::FreeQueueSize();
- if (*value >= qsize) {
- *value -= qsize;
- }
- }
- return result;
- }
-
- virtual bool VerifyNewMemory(const void* p) {
- if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kNewType);
- return true;
- }
-
- virtual bool VerifyArrayNewMemory(const void* p) {
- if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kArrayNewType);
- return true;
- }
-
- virtual bool VerifyMallocMemory(const void* p) {
- if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kMallocType);
- return true;
- }
-
- virtual bool VerifyAllMemory() {
- return MallocBlock::CheckEverything();
- }
-
- virtual bool MallocMemoryStats(int* blocks, size_t* total,
- int histogram[kMallocHistogramSize]) {
- return MallocBlock::MemoryStats(blocks, total, histogram);
- }
-
- virtual size_t GetEstimatedAllocatedSize(size_t size) {
- return size;
- }
-
- virtual size_t GetAllocatedSize(const void* p) {
- if (p) {
- RAW_CHECK(GetOwnership(p) != MallocExtension::kNotOwned,
- "ptr not allocated by tcmalloc");
- return MallocBlock::FromRawPointer(p)->data_size();
- }
- return 0;
- }
-
- virtual MallocExtension::Ownership GetOwnership(const void* p) {
- if (!p) {
- // nobody owns NULL
- return MallocExtension::kNotOwned;
- }
-
- // FIXME: note that correct GetOwnership should not touch memory
- // that is not owned by tcmalloc. Main implementation is using
- // pagemap to discover if page in question is owned by us or
- // not. But pagemap only has marks for first and last page of
- // spans. Note that if p was returned out of our memalign with
- // big alignment, then it will point outside of marked pages. Also
- // note that FromRawPointer call below requires touching memory
- // before pointer in order to handle memalign-ed chunks
- // (offset_). This leaves us with two options:
- //
- // * do FromRawPointer first and have possibility of crashing if
- // we're given not owned pointer
- //
- // * return incorrect ownership for those large memalign chunks
- //
- // I've decided to choose later, which appears to happen rarer and
- // therefore is arguably a lesser evil
-
- MallocExtension::Ownership rv = TCMallocImplementation::GetOwnership(p);
- if (rv != MallocExtension::kOwned) {
- return rv;
- }
-
- const MallocBlock* mb = MallocBlock::FromRawPointer(p);
- return TCMallocImplementation::GetOwnership(mb);
- }
-
- virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) {
- static const char* kDebugFreeQueue = "debug.free_queue";
-
- TCMallocImplementation::GetFreeListSizes(v);
-
- MallocExtension::FreeListInfo i;
- i.type = kDebugFreeQueue;
- i.min_object_size = 0;
- i.max_object_size = numeric_limits<size_t>::max();
- i.total_bytes_free = MallocBlock::FreeQueueSize();
- v->push_back(i);
- }
-
- };
-
-static union {
- char chars[sizeof(DebugMallocImplementation)];
- void *ptr;
-} debug_malloc_implementation_space;
-
-REGISTER_MODULE_INITIALIZER(debugallocation, {
-#if (__cplusplus >= 201103L)
- COMPILE_ASSERT(alignof(debug_malloc_implementation_space) >= alignof(DebugMallocImplementation),
- debug_malloc_implementation_space_is_not_properly_aligned);
-#endif
- // Either we or valgrind will control memory management. We
- // register our extension if we're the winner. Otherwise let
- // Valgrind use its own malloc (so don't register our extension).
- if (!RunningOnValgrind()) {
- DebugMallocImplementation *impl = new (debug_malloc_implementation_space.chars) DebugMallocImplementation();
- MallocExtension::Register(impl);
- }
-});
-
-REGISTER_MODULE_DESTRUCTOR(debugallocation, {
- if (!RunningOnValgrind()) {
- // When the program exits, check all blocks still in the free
- // queue for corruption.
- DanglingWriteChecker();
- }
-});
-
-// ========================================================================= //
-
-struct debug_alloc_retry_data {
- size_t size;
- int new_type;
-};
-
-static void *retry_debug_allocate(void *arg) {
- debug_alloc_retry_data *data = static_cast<debug_alloc_retry_data *>(arg);
- return DebugAllocate(data->size, data->new_type);
-}
-
-// This is mostly the same a cpp_alloc in tcmalloc.cc.
-// 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) {
- void* p = DebugAllocate(size, new_type);
- if (p != NULL) {
- return p;
- }
- struct debug_alloc_retry_data data;
- data.size = size;
- data.new_type = new_type;
- return handle_oom(retry_debug_allocate, &data,
- true, nothrow);
-}
-
-inline void* do_debug_malloc_or_debug_cpp_alloc(size_t size) {
- void* p = DebugAllocate(size, MallocBlock::kMallocType);
- if (p != NULL) {
- return p;
- }
- struct debug_alloc_retry_data data;
- data.size = size;
- data.new_type = MallocBlock::kMallocType;
- return handle_oom(retry_debug_allocate, &data,
- false, true);
-}
-
-// Exported routines
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_THROW {
- if (ThreadCache::IsUseEmergencyMalloc()) {
- return tcmalloc::EmergencyMalloc(size);
- }
- void* ptr = do_debug_malloc_or_debug_cpp_alloc(size);
- MallocHook::InvokeNewHook(ptr, size);
- return ptr;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_THROW {
- if (tcmalloc::IsEmergencyPtr(ptr)) {
- return tcmalloc::EmergencyFree(ptr);
- }
- MallocHook::InvokeDeleteHook(ptr);
- DebugDeallocate(ptr, MallocBlock::kMallocType, 0);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_THROW {
- MallocHook::InvokeDeleteHook(ptr);
- DebugDeallocate(ptr, MallocBlock::kMallocType, size);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t count, size_t size) PERFTOOLS_THROW {
- if (ThreadCache::IsUseEmergencyMalloc()) {
- return tcmalloc::EmergencyCalloc(count, size);
- }
- // Overflow check
- const size_t total_size = count * size;
- if (size != 0 && total_size / size != count) return NULL;
-
- void* block = do_debug_malloc_or_debug_cpp_alloc(total_size);
- MallocHook::InvokeNewHook(block, total_size);
- if (block) memset(block, 0, total_size);
- return block;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_THROW {
- if (tcmalloc::IsEmergencyPtr(ptr)) {
- return tcmalloc::EmergencyFree(ptr);
- }
- MallocHook::InvokeDeleteHook(ptr);
- DebugDeallocate(ptr, MallocBlock::kMallocType, 0);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_THROW {
- if (tcmalloc::IsEmergencyPtr(ptr)) {
- return tcmalloc::EmergencyRealloc(ptr, size);
- }
- if (ptr == NULL) {
- ptr = do_debug_malloc_or_debug_cpp_alloc(size);
- MallocHook::InvokeNewHook(ptr, size);
- return ptr;
- }
- if (size == 0) {
- MallocHook::InvokeDeleteHook(ptr);
- DebugDeallocate(ptr, MallocBlock::kMallocType, 0);
- return NULL;
- }
- MallocBlock* old = MallocBlock::FromRawPointer(ptr);
- old->Check(MallocBlock::kMallocType);
- MallocBlock* p = MallocBlock::Allocate(size, MallocBlock::kMallocType);
-
- // If realloc fails we are to leave the old block untouched and
- // return null
- if (p == NULL) return NULL;
-
- // if ptr was allocated via memalign, then old->data_size() is not
- // start of user data. So we must be careful to copy only user-data
- char *old_begin = (char *)old->data_addr();
- char *old_end = old_begin + old->data_size();
-
- ssize_t old_ssize = old_end - (char *)ptr;
- CHECK_CONDITION(old_ssize >= 0);
-
- size_t old_size = (size_t)old_ssize;
- CHECK_CONDITION(old_size <= old->data_size());
-
- memcpy(p->data_addr(), ptr, (old_size < size) ? old_size : size);
- MallocHook::InvokeDeleteHook(ptr);
- MallocHook::InvokeNewHook(p->data_addr(), size);
- DebugDeallocate(ptr, MallocBlock::kMallocType, 0);
- MALLOC_TRACE("realloc", p->data_size(), p->data_addr());
- return p->data_addr();
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_new(size_t size) {
- void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, false);
- MallocHook::InvokeNewHook(ptr, size);
- if (ptr == NULL) {
- RAW_LOG(FATAL, "Unable to allocate %" PRIuS " bytes: new failed.", size);
- }
- return ptr;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) PERFTOOLS_THROW {
- void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, true);
- MallocHook::InvokeNewHook(ptr, size);
- return ptr;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_THROW {
- MallocHook::InvokeDeleteHook(p);
- DebugDeallocate(p, MallocBlock::kNewType, 0);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) throw() {
- MallocHook::InvokeDeleteHook(p);
- DebugDeallocate(p, MallocBlock::kNewType, size);
-}
-
-// Some STL implementations explicitly invoke this.
-// It is completely equivalent to a normal delete (delete never throws).
-extern "C" PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, const std::nothrow_t&) PERFTOOLS_THROW {
- MallocHook::InvokeDeleteHook(p);
- DebugDeallocate(p, MallocBlock::kNewType, 0);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) {
- void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, false);
- MallocHook::InvokeNewHook(ptr, size);
- if (ptr == NULL) {
- RAW_LOG(FATAL, "Unable to allocate %" PRIuS " bytes: new[] failed.", size);
- }
- return ptr;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&)
- PERFTOOLS_THROW {
- void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, true);
- MallocHook::InvokeNewHook(ptr, size);
- return ptr;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_THROW {
- MallocHook::InvokeDeleteHook(p);
- DebugDeallocate(p, MallocBlock::kArrayNewType, 0);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) throw() {
- MallocHook::InvokeDeleteHook(p);
- DebugDeallocate(p, MallocBlock::kArrayNewType, size);
-}
-
-// Some STL implementations explicitly invoke this.
-// It is completely equivalent to a normal delete (delete never throws).
-extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, const std::nothrow_t&) PERFTOOLS_THROW {
- MallocHook::InvokeDeleteHook(p);
- DebugDeallocate(p, MallocBlock::kArrayNewType, 0);
-}
-
-// This is mostly the same as do_memalign in tcmalloc.cc.
-static void *do_debug_memalign(size_t alignment, size_t size) {
- // Allocate >= size bytes aligned on "alignment" boundary
- // "alignment" is a power of two.
- void *p = 0;
- RAW_CHECK((alignment & (alignment-1)) == 0, "must be power of two");
- const size_t data_offset = MallocBlock::data_offset();
- // Allocate "alignment-1" extra bytes to ensure alignment is possible, and
- // a further data_offset bytes for an additional fake header.
- size_t extra_bytes = data_offset + alignment - 1;
- if (size + extra_bytes < size) return NULL; // Overflow
- p = DebugAllocate(size + extra_bytes, MallocBlock::kMallocType);
- if (p != 0) {
- intptr_t orig_p = reinterpret_cast<intptr_t>(p);
- // Leave data_offset bytes for fake header, and round up to meet
- // alignment.
- p = reinterpret_cast<void *>(RoundUp(orig_p + data_offset, alignment));
- // Create a fake header block with an offset_ that points back to the
- // real header. FromRawPointer uses this value.
- MallocBlock *fake_hdr = reinterpret_cast<MallocBlock *>(
- reinterpret_cast<char *>(p) - data_offset);
- // offset_ is distance between real and fake headers.
- // p is now end of fake header (beginning of client area),
- // and orig_p is the end of the real header, so offset_
- // is their difference.
- //
- // Note that other fields of fake_hdr are initialized with
- // kMagicUninitializedByte
- fake_hdr->set_offset(reinterpret_cast<intptr_t>(p) - orig_p);
- }
- return p;
-}
-
-struct memalign_retry_data {
- size_t align;
- size_t size;
-};
-
-static void *retry_debug_memalign(void *arg) {
- memalign_retry_data *data = static_cast<memalign_retry_data *>(arg);
- return do_debug_memalign(data->align, data->size);
-}
-
-inline void* do_debug_memalign_or_debug_cpp_memalign(size_t align,
- size_t size) {
- void* p = do_debug_memalign(align, size);
- if (p != NULL) {
- return p;
- }
-
- struct memalign_retry_data data;
- data.align = align;
- data.size = size;
- return handle_oom(retry_debug_memalign, &data,
- false, true);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align, size_t size) PERFTOOLS_THROW {
- void *p = do_debug_memalign_or_debug_cpp_memalign(align, size);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-// Implementation taken from tcmalloc/tcmalloc.cc
-extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign(void** result_ptr, size_t align, size_t size)
- PERFTOOLS_THROW {
- if (((align % sizeof(void*)) != 0) ||
- ((align & (align - 1)) != 0) ||
- (align == 0)) {
- return EINVAL;
- }
-
- void* result = do_debug_memalign_or_debug_cpp_memalign(align, size);
- MallocHook::InvokeNewHook(result, size);
- if (result == NULL) {
- return ENOMEM;
- } else {
- *result_ptr = result;
- return 0;
- }
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) PERFTOOLS_THROW {
- // Allocate >= size bytes starting on a page boundary
- void *p = do_debug_memalign_or_debug_cpp_memalign(getpagesize(), size);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) PERFTOOLS_THROW {
- // Round size up to a multiple of pages
- // then allocate memory on a page boundary
- int pagesize = getpagesize();
- size = RoundUp(size, pagesize);
- if (size == 0) { // pvalloc(0) should allocate one page, according to
- size = pagesize; // http://man.free4web.biz/man3/libmpatrol.3.html
- }
- void *p = do_debug_memalign_or_debug_cpp_memalign(pagesize, size);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-// malloc_stats just falls through to the base implementation.
-extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_THROW {
- do_malloc_stats();
-}
-
-extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_THROW {
- return do_mallopt(cmd, value);
-}
-
-#ifdef HAVE_STRUCT_MALLINFO
-extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_THROW {
- return do_mallinfo();
-}
-#endif
-
-extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_THROW {
- return MallocExtension::instance()->GetAllocatedSize(ptr);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_THROW {
- void* result = DebugAllocate(size, MallocBlock::kMallocType);
- MallocHook::InvokeNewHook(result, size);
- return result;
-}
diff --git a/src/third_party/gperftools-2.5/src/emergency_malloc.cc b/src/third_party/gperftools-2.5/src/emergency_malloc.cc
deleted file mode 100644
index 81c55541ad2..00000000000
--- a/src/third_party/gperftools-2.5/src/emergency_malloc.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2014, gperftools Contributors
-// 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.
-//
-
-#include "config.h"
-
-#include "emergency_malloc.h"
-
-#include <errno.h> // for ENOMEM, errno
-#include <string.h> // for memset
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/low_level_alloc.h"
-#include "base/spinlock.h"
-#include "internal_logging.h"
-
-
-namespace tcmalloc {
- __attribute__ ((visibility("internal"))) char *emergency_arena_start;
- __attribute__ ((visibility("internal"))) uintptr_t emergency_arena_start_shifted;
-
- static CACHELINE_ALIGNED SpinLock emergency_malloc_lock(base::LINKER_INITIALIZED);
- static char *emergency_arena_end;
- static LowLevelAlloc::Arena *emergency_arena;
-
- class EmergencyArenaPagesAllocator : public LowLevelAlloc::PagesAllocator {
- ~EmergencyArenaPagesAllocator() {}
- void *MapPages(int32 flags, size_t size) {
- char *new_end = emergency_arena_end + size;
- if (new_end > emergency_arena_start + kEmergencyArenaSize) {
- RAW_LOG(FATAL, "Unable to allocate %" PRIuS " bytes in emergency zone.", size);
- }
- char *rv = emergency_arena_end;
- emergency_arena_end = new_end;
- return static_cast<void *>(rv);
- }
- void UnMapPages(int32 flags, void *addr, size_t size) {
- RAW_LOG(FATAL, "UnMapPages is not implemented for emergency arena");
- }
- };
-
- static union {
- char bytes[sizeof(EmergencyArenaPagesAllocator)];
- void *ptr;
- } pages_allocator_place;
-
- static void InitEmergencyMalloc(void) {
- const int32 flags = LowLevelAlloc::kAsyncSignalSafe;
-
- void *arena = LowLevelAlloc::GetDefaultPagesAllocator()->MapPages(flags, kEmergencyArenaSize * 2);
-
- uintptr_t arena_ptr = reinterpret_cast<uintptr_t>(arena);
- uintptr_t ptr = (arena_ptr + kEmergencyArenaSize - 1) & ~(kEmergencyArenaSize-1);
-
- emergency_arena_end = emergency_arena_start = reinterpret_cast<char *>(ptr);
- EmergencyArenaPagesAllocator *allocator = new (pages_allocator_place.bytes) EmergencyArenaPagesAllocator();
- emergency_arena = LowLevelAlloc::NewArenaWithCustomAlloc(0, LowLevelAlloc::DefaultArena(), allocator);
-
- emergency_arena_start_shifted = reinterpret_cast<uintptr_t>(emergency_arena_start) >> kEmergencyArenaShift;
-
- uintptr_t head_unmap_size = ptr - arena_ptr;
- CHECK_CONDITION(head_unmap_size < kEmergencyArenaSize);
- if (head_unmap_size != 0) {
- LowLevelAlloc::GetDefaultPagesAllocator()->UnMapPages(flags, arena, ptr - arena_ptr);
- }
-
- uintptr_t tail_unmap_size = kEmergencyArenaSize - head_unmap_size;
- void *tail_start = reinterpret_cast<void *>(arena_ptr + head_unmap_size + kEmergencyArenaSize);
- LowLevelAlloc::GetDefaultPagesAllocator()->UnMapPages(flags, tail_start, tail_unmap_size);
- }
-
- PERFTOOLS_DLL_DECL void *EmergencyMalloc(size_t size) {
- SpinLockHolder l(&emergency_malloc_lock);
-
- if (emergency_arena_start == NULL) {
- InitEmergencyMalloc();
- CHECK_CONDITION(emergency_arena_start != NULL);
- }
-
- void *rv = LowLevelAlloc::AllocWithArena(size, emergency_arena);
- if (rv == NULL) {
- errno = ENOMEM;
- }
- return rv;
- }
-
- PERFTOOLS_DLL_DECL void EmergencyFree(void *p) {
- SpinLockHolder l(&emergency_malloc_lock);
- if (emergency_arena_start == NULL) {
- InitEmergencyMalloc();
- CHECK_CONDITION(emergency_arena_start != NULL);
- free(p);
- return;
- }
- CHECK_CONDITION(emergency_arena_start);
- LowLevelAlloc::Free(p);
- }
-
- PERFTOOLS_DLL_DECL void *EmergencyRealloc(void *_old_ptr, size_t new_size) {
- if (_old_ptr == NULL) {
- return EmergencyMalloc(new_size);
- }
- if (new_size == 0) {
- EmergencyFree(_old_ptr);
- return NULL;
- }
- SpinLockHolder l(&emergency_malloc_lock);
- CHECK_CONDITION(emergency_arena_start);
-
- char *old_ptr = static_cast<char *>(_old_ptr);
- CHECK_CONDITION(old_ptr <= emergency_arena_end);
- CHECK_CONDITION(emergency_arena_start <= old_ptr);
-
- // NOTE: we don't know previous size of old_ptr chunk. So instead
- // of trying to figure out right size of copied memory, we just
- // copy largest possible size. We don't care about being slow.
- size_t old_ptr_size = emergency_arena_end - old_ptr;
- size_t copy_size = (new_size < old_ptr_size) ? new_size : old_ptr_size;
-
- void *new_ptr = LowLevelAlloc::AllocWithArena(new_size, emergency_arena);
- if (new_ptr == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- memcpy(new_ptr, old_ptr, copy_size);
-
- LowLevelAlloc::Free(old_ptr);
- return new_ptr;
- }
-
- PERFTOOLS_DLL_DECL void *EmergencyCalloc(size_t n, size_t elem_size) {
- // Overflow check
- const size_t size = n * elem_size;
- if (elem_size != 0 && size / elem_size != n) return NULL;
- void *rv = EmergencyMalloc(size);
- if (rv != NULL) {
- memset(rv, 0, size);
- }
- return rv;
- }
-};
diff --git a/src/third_party/gperftools-2.5/src/emergency_malloc.h b/src/third_party/gperftools-2.5/src/emergency_malloc.h
deleted file mode 100644
index 8ec53d231c5..00000000000
--- a/src/third_party/gperftools-2.5/src/emergency_malloc.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2014, gperftools Contributors
-// 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.
-
-#ifndef EMERGENCY_MALLOC_H
-#define EMERGENCY_MALLOC_H
-#include "config.h"
-
-#include <stddef.h>
-
-#include "base/basictypes.h"
-#include "common.h"
-
-namespace tcmalloc {
- static const uintptr_t kEmergencyArenaShift = 20+4; // 16 megs
- static const uintptr_t kEmergencyArenaSize = 1 << kEmergencyArenaShift;
-
- extern __attribute__ ((visibility("internal"))) char *emergency_arena_start;
- extern __attribute__ ((visibility("internal"))) uintptr_t emergency_arena_start_shifted;;
-
- PERFTOOLS_DLL_DECL void *EmergencyMalloc(size_t size);
- PERFTOOLS_DLL_DECL void EmergencyFree(void *p);
- PERFTOOLS_DLL_DECL void *EmergencyCalloc(size_t n, size_t elem_size);
- PERFTOOLS_DLL_DECL void *EmergencyRealloc(void *old_ptr, size_t new_size);
-
- static inline bool IsEmergencyPtr(const void *_ptr) {
- uintptr_t ptr = reinterpret_cast<uintptr_t>(_ptr);
- return UNLIKELY((ptr >> kEmergencyArenaShift) == emergency_arena_start_shifted)
- && emergency_arena_start_shifted;
- }
-
-} // namespace tcmalloc
-
-#endif
diff --git a/src/third_party/gperftools-2.5/src/emergency_malloc_for_stacktrace.cc b/src/third_party/gperftools-2.5/src/emergency_malloc_for_stacktrace.cc
deleted file mode 100644
index f1dc35e76a4..00000000000
--- a/src/third_party/gperftools-2.5/src/emergency_malloc_for_stacktrace.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2014, gperftools Contributors
-// 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.
-#include "emergency_malloc.h"
-#include "thread_cache.h"
-
-namespace tcmalloc {
- bool EnterStacktraceScope(void);
- void LeaveStacktraceScope(void);
-}
-
-bool tcmalloc::EnterStacktraceScope(void) {
- if (ThreadCache::IsUseEmergencyMalloc()) {
- return false;
- }
- ThreadCache::SetUseEmergencyMalloc();
- return true;
-}
-
-void tcmalloc::LeaveStacktraceScope(void) {
- ThreadCache::ResetUseEmergencyMalloc();
-}
diff --git a/src/third_party/gperftools-2.5/src/fake_stacktrace_scope.cc b/src/third_party/gperftools-2.5/src/fake_stacktrace_scope.cc
deleted file mode 100644
index ee35a041252..00000000000
--- a/src/third_party/gperftools-2.5/src/fake_stacktrace_scope.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2014, gperftools Contributors
-// 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.
-
-#include "base/basictypes.h"
-
-namespace tcmalloc {
- ATTRIBUTE_WEAK bool EnterStacktraceScope(void) {
- return true;
- }
- ATTRIBUTE_WEAK void LeaveStacktraceScope(void) {
- }
-}
diff --git a/src/third_party/gperftools-2.5/src/getenv_safe.h b/src/third_party/gperftools-2.5/src/getenv_safe.h
deleted file mode 100644
index 3b9f4dbbcb2..00000000000
--- a/src/third_party/gperftools-2.5/src/getenv_safe.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
- * Copyright (c) 2014, gperftools Contributors
- * 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.
- */
-
-#ifndef GETENV_SAFE_H
-#define GETENV_SAFE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * This getenv function is safe to call before the C runtime is initialized.
- * On Windows, it utilizes GetEnvironmentVariable() and on unix it uses
- * /proc/self/environ instead calling getenv(). It's intended to be used in
- * routines that run before main(), when the state required for getenv() may
- * not be set up yet. In particular, errno isn't set up until relatively late
- * (after the pthreads library has a chance to make it threadsafe), and
- * getenv() doesn't work until then.
- * On some platforms, this call will utilize the same, static buffer for
- * repeated GetenvBeforeMain() calls. Callers should not expect pointers from
- * this routine to be long lived.
- * Note that on unix, /proc only has the environment at the time the
- * application was started, so this routine ignores setenv() calls/etc. Also
- * note it only reads the first 16K of the environment.
- *
- * NOTE: this is version of GetenvBeforeMain that's usable from
- * C. Implementation is in sysinfo.cc
- */
-const char* TCMallocGetenvSafe(const char* name);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/third_party/gperftools-2.5/src/getpc.h b/src/third_party/gperftools-2.5/src/getpc.h
deleted file mode 100644
index 25fee3931c7..00000000000
--- a/src/third_party/gperftools-2.5/src/getpc.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Craig Silverstein
-//
-// This is an internal header file used by profiler.cc. It defines
-// the single (inline) function GetPC. GetPC is used in a signal
-// handler to figure out the instruction that was being executed when
-// the signal-handler was triggered.
-//
-// To get this, we use the ucontext_t argument to the signal-handler
-// callback, which holds the full context of what was going on when
-// the signal triggered. How to get from a ucontext_t to a Program
-// Counter is OS-dependent.
-
-#ifndef BASE_GETPC_H_
-#define BASE_GETPC_H_
-
-#include "config.h"
-
-// On many linux systems, we may need _GNU_SOURCE to get access to
-// the defined constants that define the register we want to see (eg
-// REG_EIP). Note this #define must come first!
-#define _GNU_SOURCE 1
-// If #define _GNU_SOURCE causes problems, this might work instead.
-// It will cause problems for FreeBSD though!, because it turns off
-// the needed __BSD_VISIBLE.
-//#define _XOPEN_SOURCE 500
-
-#include <string.h> // for memcmp
-#if defined(HAVE_SYS_UCONTEXT_H)
-#include <sys/ucontext.h>
-#elif defined(HAVE_UCONTEXT_H)
-#include <ucontext.h> // for ucontext_t (and also mcontext_t)
-#elif defined(HAVE_CYGWIN_SIGNAL_H)
-#include <cygwin/signal.h>
-typedef ucontext ucontext_t;
-#endif
-
-
-// Take the example where function Foo() calls function Bar(). For
-// many architectures, Bar() is responsible for setting up and tearing
-// down its own stack frame. In that case, it's possible for the
-// interrupt to happen when execution is in Bar(), but the stack frame
-// is not properly set up (either before it's done being set up, or
-// after it's been torn down but before Bar() returns). In those
-// cases, the stack trace cannot see the caller function anymore.
-//
-// GetPC can try to identify this situation, on architectures where it
-// might occur, and unwind the current function call in that case to
-// avoid false edges in the profile graph (that is, edges that appear
-// to show a call skipping over a function). To do this, we hard-code
-// in the asm instructions we might see when setting up or tearing
-// down a stack frame.
-//
-// This is difficult to get right: the instructions depend on the
-// processor, the compiler ABI, and even the optimization level. This
-// is a best effort patch -- if we fail to detect such a situation, or
-// mess up the PC, nothing happens; the returned PC is not used for
-// any further processing.
-struct CallUnrollInfo {
- // Offset from (e)ip register where this instruction sequence
- // should be matched. Interpreted as bytes. Offset 0 is the next
- // instruction to execute. Be extra careful with negative offsets in
- // architectures of variable instruction length (like x86) - it is
- // not that easy as taking an offset to step one instruction back!
- int pc_offset;
- // The actual instruction bytes. Feel free to make it larger if you
- // need a longer sequence.
- unsigned char ins[16];
- // How many bytes to match from ins array?
- int ins_size;
- // The offset from the stack pointer (e)sp where to look for the
- // call return address. Interpreted as bytes.
- int return_sp_offset;
-};
-
-
-// The dereferences needed to get the PC from a struct ucontext were
-// determined at configure time, and stored in the macro
-// PC_FROM_UCONTEXT in config.h. The only thing we need to do here,
-// then, is to do the magic call-unrolling for systems that support it.
-
-// -- Special case 1: linux x86, for which we have CallUnrollInfo
-#if defined(__linux) && defined(__i386) && defined(__GNUC__)
-static const CallUnrollInfo callunrollinfo[] = {
- // Entry to a function: push %ebp; mov %esp,%ebp
- // Top-of-stack contains the caller IP.
- { 0,
- {0x55, 0x89, 0xe5}, 3,
- 0
- },
- // Entry to a function, second instruction: push %ebp; mov %esp,%ebp
- // Top-of-stack contains the old frame, caller IP is +4.
- { -1,
- {0x55, 0x89, 0xe5}, 3,
- 4
- },
- // Return from a function: RET.
- // Top-of-stack contains the caller IP.
- { 0,
- {0xc3}, 1,
- 0
- }
-};
-
-inline void* GetPC(const ucontext_t& signal_ucontext) {
- // See comment above struct CallUnrollInfo. Only try instruction
- // flow matching if both eip and esp looks reasonable.
- const int eip = signal_ucontext.uc_mcontext.gregs[REG_EIP];
- const int esp = signal_ucontext.uc_mcontext.gregs[REG_ESP];
- if ((eip & 0xffff0000) != 0 && (~eip & 0xffff0000) != 0 &&
- (esp & 0xffff0000) != 0) {
- char* eip_char = reinterpret_cast<char*>(eip);
- for (int i = 0; i < sizeof(callunrollinfo)/sizeof(*callunrollinfo); ++i) {
- if (!memcmp(eip_char + callunrollinfo[i].pc_offset,
- callunrollinfo[i].ins, callunrollinfo[i].ins_size)) {
- // We have a match.
- void **retaddr = (void**)(esp + callunrollinfo[i].return_sp_offset);
- return *retaddr;
- }
- }
- }
- return (void*)eip;
-}
-
-// Special case #2: Windows, which has to do something totally different.
-#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__)
-// If this is ever implemented, probably the way to do it is to have
-// profiler.cc use a high-precision timer via timeSetEvent:
-// http://msdn2.microsoft.com/en-us/library/ms712713.aspx
-// We'd use it in mode TIME_CALLBACK_FUNCTION/TIME_PERIODIC.
-// The callback function would be something like prof_handler, but
-// alas the arguments are different: no ucontext_t! I don't know
-// how we'd get the PC (using StackWalk64?)
-// http://msdn2.microsoft.com/en-us/library/ms680650.aspx
-
-#include "base/logging.h" // for RAW_LOG
-#ifndef HAVE_CYGWIN_SIGNAL_H
-typedef int ucontext_t;
-#endif
-
-inline void* GetPC(const struct ucontext_t& signal_ucontext) {
- RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n");
- return NULL;
-}
-
-// Normal cases. If this doesn't compile, it's probably because
-// PC_FROM_UCONTEXT is the empty string. You need to figure out
-// the right value for your system, and add it to the list in
-// configure.ac (or set it manually in your config.h).
-#else
-inline void* GetPC(const ucontext_t& signal_ucontext) {
- return (void*)signal_ucontext.PC_FROM_UCONTEXT; // defined in config.h
-}
-
-#endif
-
-#endif // BASE_GETPC_H_
diff --git a/src/third_party/gperftools-2.5/src/google/heap-checker.h b/src/third_party/gperftools-2.5/src/google/heap-checker.h
deleted file mode 100644
index 7cacf1f0094..00000000000
--- a/src/third_party/gperftools-2.5/src/google/heap-checker.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-/* The code has moved to gperftools/. Use that include-directory for
- * new code.
- */
-#ifdef __GNUC__
-#warning "google/heap-checker.h is deprecated. Use gperftools/heap-checker.h instead"
-#endif
-#include <gperftools/heap-checker.h>
diff --git a/src/third_party/gperftools-2.5/src/google/heap-profiler.h b/src/third_party/gperftools-2.5/src/google/heap-profiler.h
deleted file mode 100644
index 3fc26cf7378..00000000000
--- a/src/third_party/gperftools-2.5/src/google/heap-profiler.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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.
- */
-
-/* The code has moved to gperftools/. Use that include-directory for
- * new code.
- */
-#ifdef __GNUC__
-#warning "google/heap-profiler.h is deprecated. Use gperftools/heap-profiler.h instead"
-#endif
-#include <gperftools/heap-profiler.h>
diff --git a/src/third_party/gperftools-2.5/src/google/malloc_extension.h b/src/third_party/gperftools-2.5/src/google/malloc_extension.h
deleted file mode 100644
index 7cacc348158..00000000000
--- a/src/third_party/gperftools-2.5/src/google/malloc_extension.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-/* The code has moved to gperftools/. Use that include-directory for
- * new code.
- */
-#ifdef __GNUC__
-#warning "google/malloc_extension.h is deprecated. Use gperftools/malloc_extension.h instead"
-#endif
-#include <gperftools/malloc_extension.h>
diff --git a/src/third_party/gperftools-2.5/src/google/malloc_extension_c.h b/src/third_party/gperftools-2.5/src/google/malloc_extension_c.h
deleted file mode 100644
index f34a835d823..00000000000
--- a/src/third_party/gperftools-2.5/src/google/malloc_extension_c.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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.
- */
-
-/* The code has moved to gperftools/. Use that include-directory for
- * new code.
- */
-#ifdef __GNUC__
-#warning "google/malloc_extension_c.h is deprecated. Use gperftools/malloc_extension_c.h instead"
-#endif
-#include <gperftools/malloc_extension_c.h>
diff --git a/src/third_party/gperftools-2.5/src/google/malloc_hook.h b/src/third_party/gperftools-2.5/src/google/malloc_hook.h
deleted file mode 100644
index 371aba476f1..00000000000
--- a/src/third_party/gperftools-2.5/src/google/malloc_hook.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-/* The code has moved to gperftools/. Use that include-directory for
- * new code.
- */
-#ifdef __GNUC__
-#warning "google/malloc_hook.h is deprecated. Use gperftools/malloc_hook.h instead"
-#endif
-#include <gperftools/malloc_hook.h>
diff --git a/src/third_party/gperftools-2.5/src/google/malloc_hook_c.h b/src/third_party/gperftools-2.5/src/google/malloc_hook_c.h
deleted file mode 100644
index f882c16d64d..00000000000
--- a/src/third_party/gperftools-2.5/src/google/malloc_hook_c.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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.
- */
-
-/* The code has moved to gperftools/. Use that include-directory for
- * new code.
- */
-#ifdef __GNUC__
-#warning "google/malloc_hook_c.h is deprecated. Use gperftools/malloc_hook_c.h instead"
-#endif
-#include <gperftools/malloc_hook_c.h>
diff --git a/src/third_party/gperftools-2.5/src/google/profiler.h b/src/third_party/gperftools-2.5/src/google/profiler.h
deleted file mode 100644
index 3674c9e379d..00000000000
--- a/src/third_party/gperftools-2.5/src/google/profiler.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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.
- */
-
-/* The code has moved to gperftools/. Use that include-directory for
- * new code.
- */
-#ifdef __GNUC__
-#warning "google/profiler.h is deprecated. Use gperftools/profiler.h instead"
-#endif
-#include <gperftools/profiler.h>
diff --git a/src/third_party/gperftools-2.5/src/google/stacktrace.h b/src/third_party/gperftools-2.5/src/google/stacktrace.h
deleted file mode 100644
index 53d29472a1d..00000000000
--- a/src/third_party/gperftools-2.5/src/google/stacktrace.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-/* The code has moved to gperftools/. Use that include-directory for
- * new code.
- */
-#ifdef __GNUC__
-#warning "google/stacktrace.h is deprecated. Use gperftools/stacktrace.h instead"
-#endif
-#include <gperftools/stacktrace.h>
diff --git a/src/third_party/gperftools-2.5/src/google/tcmalloc.h b/src/third_party/gperftools-2.5/src/google/tcmalloc.h
deleted file mode 100644
index a2db70e2f37..00000000000
--- a/src/third_party/gperftools-2.5/src/google/tcmalloc.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (c) 2003, 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.
- */
-
-/* The code has moved to gperftools/. Use that include-directory for
- * new code.
- */
-#ifdef __GNUC__
-#warning "google/tcmalloc.h is deprecated. Use gperftools/tcmalloc.h instead"
-#endif
-#include <gperftools/tcmalloc.h>
diff --git a/src/third_party/gperftools-2.5/src/gperftools/heap-checker.h b/src/third_party/gperftools-2.5/src/gperftools/heap-checker.h
deleted file mode 100644
index 5a87d8da7f7..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/heap-checker.h
+++ /dev/null
@@ -1,422 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Maxim Lifantsev (with design ideas by Sanjay Ghemawat)
-//
-//
-// Module for detecing heap (memory) leaks.
-//
-// For full(er) information, see doc/heap_checker.html
-//
-// This module can be linked into programs with
-// no slowdown caused by this unless you activate the leak-checker:
-//
-// 1. Set the environment variable HEAPCHEK to _type_ before
-// running the program.
-//
-// _type_ is usually "normal" but can also be "minimal", "strict", or
-// "draconian". (See the html file for other options, like 'local'.)
-//
-// After that, just run your binary. If the heap-checker detects
-// a memory leak at program-exit, it will print instructions on how
-// to track down the leak.
-
-#ifndef BASE_HEAP_CHECKER_H_
-#define BASE_HEAP_CHECKER_H_
-
-#include <sys/types.h> // for size_t
-// I can't #include config.h in this public API file, but I should
-// really use configure (and make malloc_extension.h a .in file) to
-// figure out if the system has stdint.h or not. But I'm lazy, so
-// for now I'm assuming it's a problem only with MSVC.
-#ifndef _MSC_VER
-#include <stdint.h> // for uintptr_t
-#endif
-#include <stdarg.h> // for va_list
-#include <vector>
-
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef PERFTOOLS_DLL_DECL
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-
-// The class is thread-safe with respect to all the provided static methods,
-// as well as HeapLeakChecker objects: they can be accessed by multiple threads.
-class PERFTOOLS_DLL_DECL HeapLeakChecker {
- public:
-
- // ----------------------------------------------------------------------- //
- // Static functions for working with (whole-program) leak checking.
-
- // If heap leak checking is currently active in some mode
- // e.g. if leak checking was started (and is still active now)
- // due to HEAPCHECK=... defined in the environment.
- // The return value reflects iff HeapLeakChecker objects manually
- // constructed right now will be doing leak checking or nothing.
- // Note that we can go from active to inactive state during InitGoogle()
- // if FLAGS_heap_check gets set to "" by some code before/during InitGoogle().
- static bool IsActive();
-
- // Return pointer to the whole-program checker if it has been created
- // and NULL otherwise.
- // Once GlobalChecker() returns non-NULL that object will not disappear and
- // will be returned by all later GlobalChecker calls.
- // This is mainly to access BytesLeaked() and ObjectsLeaked() (see below)
- // for the whole-program checker after one calls NoGlobalLeaks()
- // or similar and gets false.
- static HeapLeakChecker* GlobalChecker();
-
- // Do whole-program leak check now (if it was activated for this binary);
- // return false only if it was activated and has failed.
- // The mode of the check is controlled by the command-line flags.
- // This method can be called repeatedly.
- // Things like GlobalChecker()->SameHeap() can also be called explicitly
- // to do the desired flavor of the check.
- static bool NoGlobalLeaks();
-
- // If whole-program checker if active,
- // cancel its automatic execution after main() exits.
- // This requires that some leak check (e.g. NoGlobalLeaks())
- // has been called at least once on the whole-program checker.
- static void CancelGlobalCheck();
-
- // ----------------------------------------------------------------------- //
- // Non-static functions for starting and doing leak checking.
-
- // Start checking and name the leak check performed.
- // The name is used in naming dumped profiles
- // and needs to be unique only within your binary.
- // It must also be a string that can be a part of a file name,
- // in particular not contain path expressions.
- explicit HeapLeakChecker(const char *name);
-
- // Destructor (verifies that some *NoLeaks or *SameHeap method
- // has been called at least once).
- ~HeapLeakChecker();
-
- // These used to be different but are all the same now: they return
- // true iff all memory allocated since this HeapLeakChecker object
- // was constructor is still reachable from global state.
- //
- // Because we fork to convert addresses to symbol-names, and forking
- // is not thread-safe, and we may be called in a threaded context,
- // we do not try to symbolize addresses when called manually.
- bool NoLeaks() { return DoNoLeaks(DO_NOT_SYMBOLIZE); }
-
- // These forms are obsolete; use NoLeaks() instead.
- // TODO(csilvers): mark as DEPRECATED.
- bool QuickNoLeaks() { return NoLeaks(); }
- bool BriefNoLeaks() { return NoLeaks(); }
- bool SameHeap() { return NoLeaks(); }
- bool QuickSameHeap() { return NoLeaks(); }
- bool BriefSameHeap() { return NoLeaks(); }
-
- // Detailed information about the number of leaked bytes and objects
- // (both of these can be negative as well).
- // These are available only after a *SameHeap or *NoLeaks
- // method has been called.
- // Note that it's possible for both of these to be zero
- // while SameHeap() or NoLeaks() returned false in case
- // of a heap state change that is significant
- // but preserves the byte and object counts.
- ssize_t BytesLeaked() const;
- ssize_t ObjectsLeaked() const;
-
- // ----------------------------------------------------------------------- //
- // Static helpers to make us ignore certain leaks.
-
- // Scoped helper class. Should be allocated on the stack inside a
- // block of code. Any heap allocations done in the code block
- // covered by the scoped object (including in nested function calls
- // done by the code block) will not be reported as leaks. This is
- // the recommended replacement for the GetDisableChecksStart() and
- // DisableChecksToHereFrom() routines below.
- //
- // Example:
- // void Foo() {
- // HeapLeakChecker::Disabler disabler;
- // ... code that allocates objects whose leaks should be ignored ...
- // }
- //
- // REQUIRES: Destructor runs in same thread as constructor
- class Disabler {
- public:
- Disabler();
- ~Disabler();
- private:
- Disabler(const Disabler&); // disallow copy
- void operator=(const Disabler&); // and assign
- };
-
- // Ignore an object located at 'ptr' (can go at the start or into the object)
- // as well as all heap objects (transitively) referenced from it for the
- // purposes of heap leak checking. Returns 'ptr' so that one can write
- // static T* obj = IgnoreObject(new T(...));
- //
- // 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.
- //
- // See also HiddenPointer, below, if you need to prevent a pointer from
- // being traversed by the heap checker but do not wish to transitively
- // whitelist objects referenced through it.
- template <typename T>
- static T* IgnoreObject(T* ptr) {
- DoIgnoreObject(static_cast<const void*>(const_cast<const T*>(ptr)));
- return ptr;
- }
-
- // Undo what an earlier IgnoreObject() call promised and asked to do.
- // At the time of this call 'ptr' must point at or inside of an active
- // allocated object which was previously registered with IgnoreObject().
- static void UnIgnoreObject(const void* ptr);
-
- // ----------------------------------------------------------------------- //
- // Internal types defined in .cc
-
- class Allocator;
- struct RangeValue;
-
- private:
-
- // ----------------------------------------------------------------------- //
- // Various helpers
-
- // Create the name of the heap profile file.
- // Should be deleted via Allocator::Free().
- char* MakeProfileNameLocked();
-
- // Helper for constructors
- void Create(const char *name, bool make_start_snapshot);
-
- enum ShouldSymbolize { SYMBOLIZE, DO_NOT_SYMBOLIZE };
-
- // Helper for *NoLeaks and *SameHeap
- bool DoNoLeaks(ShouldSymbolize should_symbolize);
-
- // Helper for NoGlobalLeaks, also called by the global destructor.
- static bool NoGlobalLeaksMaybeSymbolize(ShouldSymbolize should_symbolize);
-
- // These used to be public, but they are now deprecated.
- // Will remove entirely when all internal uses are fixed.
- // In the meantime, use friendship so the unittest can still test them.
- static void* GetDisableChecksStart();
- static void DisableChecksToHereFrom(const void* start_address);
- static void DisableChecksIn(const char* pattern);
- friend void RangeDisabledLeaks();
- friend void NamedTwoDisabledLeaks();
- friend void* RunNamedDisabledLeaks(void*);
- friend void TestHeapLeakCheckerNamedDisabling();
-
- // Actually implements IgnoreObject().
- static void DoIgnoreObject(const void* ptr);
-
- // Disable checks based on stack trace entry at a depth <=
- // max_depth. Used to hide allocations done inside some special
- // libraries.
- static void DisableChecksFromToLocked(const void* start_address,
- const void* end_address,
- int max_depth);
-
- // Helper for DoNoLeaks to ignore all objects reachable from all live data
- static void IgnoreAllLiveObjectsLocked(const void* self_stack_top);
-
- // Callback we pass to TCMalloc_ListAllProcessThreads (see thread_lister.h)
- // that is invoked when all threads of our process are found and stopped.
- // The call back does the things needed to ignore live data reachable from
- // thread stacks and registers for all our threads
- // as well as do other global-live-data ignoring
- // (via IgnoreNonThreadLiveObjectsLocked)
- // during the quiet state of all threads being stopped.
- // For the argument meaning see the comment by TCMalloc_ListAllProcessThreads.
- // Here we only use num_threads and thread_pids, that TCMalloc_ListAllProcessThreads
- // fills for us with the number and pids of all the threads of our process
- // it found and attached to.
- static int IgnoreLiveThreadsLocked(void* parameter,
- int num_threads,
- pid_t* thread_pids,
- va_list ap);
-
- // Helper for IgnoreAllLiveObjectsLocked and IgnoreLiveThreadsLocked
- // that we prefer to execute from IgnoreLiveThreadsLocked
- // while all threads are stopped.
- // This helper does live object discovery and ignoring
- // for all objects that are reachable from everything
- // not related to thread stacks and registers.
- static void IgnoreNonThreadLiveObjectsLocked();
-
- // Helper for IgnoreNonThreadLiveObjectsLocked and IgnoreLiveThreadsLocked
- // to discover and ignore all heap objects
- // reachable from currently considered live objects
- // (live_objects static global variable in out .cc file).
- // "name", "name2" are two strings that we print one after another
- // in a debug message to describe what kind of live object sources
- // are being used.
- static void IgnoreLiveObjectsLocked(const char* name, const char* name2);
-
- // Do the overall whole-program heap leak check if needed;
- // returns true when did the leak check.
- static bool DoMainHeapCheck();
-
- // Type of task for UseProcMapsLocked
- enum ProcMapsTask {
- RECORD_GLOBAL_DATA,
- DISABLE_LIBRARY_ALLOCS
- };
-
- // Success/Error Return codes for UseProcMapsLocked.
- enum ProcMapsResult {
- PROC_MAPS_USED,
- CANT_OPEN_PROC_MAPS,
- NO_SHARED_LIBS_IN_PROC_MAPS
- };
-
- // Read /proc/self/maps, parse it, and do the 'proc_maps_task' for each line.
- static ProcMapsResult UseProcMapsLocked(ProcMapsTask proc_maps_task);
-
- // A ProcMapsTask to disable allocations from 'library'
- // that is mapped to [start_address..end_address)
- // (only if library is a certain system library).
- static void DisableLibraryAllocsLocked(const char* library,
- uintptr_t start_address,
- uintptr_t end_address);
-
- // Return true iff "*ptr" points to a heap object
- // ("*ptr" can point at the start or inside of a heap object
- // so that this works e.g. for pointers to C++ arrays, C++ strings,
- // multiple-inherited objects, or pointers to members).
- // We also fill *object_size for this object then
- // and we move "*ptr" to point to the very start of the heap object.
- static inline bool HaveOnHeapLocked(const void** ptr, size_t* object_size);
-
- // Helper to shutdown heap leak checker when it's not needed
- // or can't function properly.
- static void TurnItselfOffLocked();
-
- // Internally-used c-tor to start whole-executable checking.
- HeapLeakChecker();
-
- // ----------------------------------------------------------------------- //
- // Friends and externally accessed helpers.
-
- // Helper for VerifyHeapProfileTableStackGet in the unittest
- // to get the recorded allocation caller for ptr,
- // which must be a heap object.
- static const void* GetAllocCaller(void* ptr);
- friend void VerifyHeapProfileTableStackGet();
-
- // This gets to execute before constructors for all global objects
- static void BeforeConstructorsLocked();
- friend void HeapLeakChecker_BeforeConstructors();
-
- // This gets to execute after destructors for all global objects
- friend void HeapLeakChecker_AfterDestructors();
-
- // Full starting of recommended whole-program checking.
- friend void HeapLeakChecker_InternalInitStart();
-
- // Runs REGISTER_HEAPCHECK_CLEANUP cleanups and potentially
- // calls DoMainHeapCheck
- friend void HeapLeakChecker_RunHeapCleanups();
-
- // ----------------------------------------------------------------------- //
- // Member data.
-
- class SpinLock* lock_; // to make HeapLeakChecker objects thread-safe
- const char* name_; // our remembered name (we own it)
- // NULL means this leak checker is a noop
-
- // Snapshot taken when the checker was created. May be NULL
- // for the global heap checker object. We use void* instead of
- // HeapProfileTable::Snapshot* to avoid including heap-profile-table.h.
- void* start_snapshot_;
-
- bool has_checked_; // if we have done the leak check, so these are ready:
- ssize_t inuse_bytes_increase_; // bytes-in-use increase for this checker
- ssize_t inuse_allocs_increase_; // allocations-in-use increase
- // for this checker
- bool keep_profiles_; // iff we should keep the heap profiles we've made
-
- // ----------------------------------------------------------------------- //
-
- // Disallow "evil" constructors.
- HeapLeakChecker(const HeapLeakChecker&);
- void operator=(const HeapLeakChecker&);
-};
-
-
-// Holds a pointer that will not be traversed by the heap checker.
-// Contrast with HeapLeakChecker::IgnoreObject(o), in which o and
-// all objects reachable from o are ignored by the heap checker.
-template <class T>
-class HiddenPointer {
- public:
- explicit HiddenPointer(T* t)
- : masked_t_(reinterpret_cast<uintptr_t>(t) ^ kHideMask) {
- }
- // Returns unhidden pointer. Be careful where you save the result.
- T* get() const { return reinterpret_cast<T*>(masked_t_ ^ kHideMask); }
-
- private:
- // Arbitrary value, but not such that xor'ing with it is likely
- // to map one valid pointer to another valid pointer:
- static const uintptr_t kHideMask =
- static_cast<uintptr_t>(0xF03A5F7BF03A5F7Bll);
- uintptr_t masked_t_;
-};
-
-// A class that exists solely to run its destructor. This class should not be
-// used directly, but instead by the REGISTER_HEAPCHECK_CLEANUP macro below.
-class PERFTOOLS_DLL_DECL HeapCleaner {
- public:
- typedef void (*void_function)(void);
- HeapCleaner(void_function f);
- static void RunHeapCleanups();
- private:
- static std::vector<void_function>* heap_cleanups_;
-};
-
-// A macro to declare module heap check cleanup tasks
-// (they run only if we are doing heap leak checking.)
-// 'body' should be the cleanup code to run. 'name' doesn't matter,
-// but must be unique amongst all REGISTER_HEAPCHECK_CLEANUP calls.
-#define REGISTER_HEAPCHECK_CLEANUP(name, body) \
- namespace { \
- void heapcheck_cleanup_##name() { body; } \
- static HeapCleaner heapcheck_cleaner_##name(&heapcheck_cleanup_##name); \
- }
-
-#endif // BASE_HEAP_CHECKER_H_
diff --git a/src/third_party/gperftools-2.5/src/gperftools/heap-profiler.h b/src/third_party/gperftools-2.5/src/gperftools/heap-profiler.h
deleted file mode 100644
index 9b673645747..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/heap-profiler.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* 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
- *
- * Module for heap-profiling.
- *
- * For full(er) information, see doc/heapprofile.html
- *
- * This module can be linked into your program with
- * no slowdown caused by this unless you activate the profiler
- * using one of the following methods:
- *
- * 1. Before starting the program, set the environment variable
- * "HEAPPROFILE" to be the name of the file to which the profile
- * data should be written.
- *
- * 2. Programmatically, start and stop the profiler using the
- * routines "HeapProfilerStart(filename)" and "HeapProfilerStop()".
- *
- */
-
-#ifndef BASE_HEAP_PROFILER_H_
-#define BASE_HEAP_PROFILER_H_
-
-#include <stddef.h>
-
-/* Annoying stuff for windows; makes sure clients can import these functions */
-#ifndef PERFTOOLS_DLL_DECL
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-/* All this code should be usable from within C apps. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Start profiling and arrange to write profile data to file names
- * of the form: "prefix.0000", "prefix.0001", ...
- */
-PERFTOOLS_DLL_DECL void HeapProfilerStart(const char* prefix);
-
-/* Returns non-zero if we are currently profiling the heap. (Returns
- * an int rather than a bool so it's usable from C.) This is true
- * between calls to HeapProfilerStart() and HeapProfilerStop(), and
- * also if the program has been run with HEAPPROFILER, or some other
- * way to turn on whole-program profiling.
- */
-int IsHeapProfilerRunning();
-
-/* Stop heap profiling. Can be restarted again with HeapProfilerStart(),
- * but the currently accumulated profiling information will be cleared.
- */
-PERFTOOLS_DLL_DECL void HeapProfilerStop();
-
-/* Dump a profile now - can be used for dumping at a hopefully
- * quiescent state in your program, in order to more easily track down
- * memory leaks. Will include the reason in the logged message
- */
-PERFTOOLS_DLL_DECL void HeapProfilerDump(const char *reason);
-
-/* Generate current heap profiling information.
- * Returns an empty string when heap profiling is not active.
- * The returned pointer is a '\0'-terminated string allocated using malloc()
- * and should be free()-ed as soon as the caller does not need it anymore.
- */
-PERFTOOLS_DLL_DECL char* GetHeapProfile();
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* BASE_HEAP_PROFILER_H_ */
diff --git a/src/third_party/gperftools-2.5/src/gperftools/malloc_extension.h b/src/third_party/gperftools-2.5/src/gperftools/malloc_extension.h
deleted file mode 100644
index a8313b954e9..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/malloc_extension.h
+++ /dev/null
@@ -1,451 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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>
-//
-// Extra extensions exported by some malloc implementations. These
-// extensions are accessed through a virtual base class so an
-// application can link against a malloc that does not implement these
-// extensions, and it will get default versions that do nothing.
-//
-// NOTE FOR C USERS: If you wish to use this functionality from within
-// a C program, see malloc_extension_c.h.
-
-#ifndef BASE_MALLOC_EXTENSION_H_
-#define BASE_MALLOC_EXTENSION_H_
-
-#include <stddef.h>
-// I can't #include config.h in this public API file, but I should
-// really use configure (and make malloc_extension.h a .in file) to
-// figure out if the system has stdint.h or not. But I'm lazy, so
-// for now I'm assuming it's a problem only with MSVC.
-#ifndef _MSC_VER
-#include <stdint.h>
-#endif
-#include <string>
-#include <vector>
-
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef PERFTOOLS_DLL_DECL
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-static const int kMallocHistogramSize = 64;
-
-// One day, we could support other types of writers (perhaps for C?)
-typedef std::string MallocExtensionWriter;
-
-namespace base {
-struct MallocRange;
-struct MallocSizeClass;
-}
-
-// Interface to a pluggable system allocator.
-class PERFTOOLS_DLL_DECL SysAllocator {
- public:
- SysAllocator() {
- }
- virtual ~SysAllocator();
-
- // Allocates "size"-byte of memory from system aligned with "alignment".
- // 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;
-};
-
-// The default implementations of the following routines do nothing.
-// All implementations should be thread-safe; the current one
-// (TCMallocImplementation) is.
-class PERFTOOLS_DLL_DECL MallocExtension {
- public:
- virtual ~MallocExtension();
-
- // Call this very early in the program execution -- say, in a global
- // constructor -- to set up parameters and state needed by all
- // instrumented malloc implemenatations. One example: this routine
- // sets environemnt variables to tell STL to use libc's malloc()
- // instead of doing its own memory management. This is safe to call
- // multiple times, as long as each time is before threads start up.
- static void Initialize();
-
- // See "verify_memory.h" to see what these routines do
- virtual bool VerifyAllMemory();
- virtual bool VerifyNewMemory(const void* p);
- virtual bool VerifyArrayNewMemory(const void* p);
- virtual bool VerifyMallocMemory(const void* p);
- virtual bool MallocMemoryStats(int* blocks, size_t* total,
- int histogram[kMallocHistogramSize]);
-
- // Get a human readable description of the following malloc data structures.
- // - Total inuse memory by application.
- // - Free memory(thread, central and page heap),
- // - Freelist of central cache, each class.
- // - Page heap freelist.
- // The state is stored as a null-terminated string
- // in a prefix of "buffer[0,buffer_length-1]".
- // REQUIRES: buffer_length > 0.
- virtual void GetStats(char* buffer, int buffer_length);
-
- // Outputs to "writer" a sample of live objects and the stack traces
- // that allocated these objects. The format of the returned output
- // is equivalent to the output of the heap profiler and can
- // therefore be passed to "pprof". This function is equivalent to
- // ReadStackTraces. The main difference is that this function returns
- // serialized data appropriately formatted for use by the pprof tool.
- // NOTE: by default, tcmalloc does not do any heap sampling, and this
- // function will always return an empty sample. To get useful
- // data from GetHeapSample, you must also set the environment
- // variable TCMALLOC_SAMPLE_PARAMETER to a value such as 524288.
- virtual void GetHeapSample(MallocExtensionWriter* writer);
-
- // Outputs to "writer" the stack traces that caused growth in the
- // address space size. The format of the returned output is
- // equivalent to the output of the heap profiler and can therefore
- // be passed to "pprof". This function is equivalent to
- // ReadHeapGrowthStackTraces. The main difference is that this function
- // returns serialized data appropriately formatted for use by the
- // pprof tool. (This does not depend on, or require,
- // TCMALLOC_SAMPLE_PARAMETER.)
- virtual void GetHeapGrowthStacks(MallocExtensionWriter* writer);
-
- // Invokes func(arg, range) for every controlled memory
- // range. *range is filled in with information about the range.
- //
- // This is a best-effort interface useful only for performance
- // analysis. The implementation may not call func at all.
- typedef void (RangeFunction)(void*, const base::MallocRange*);
- virtual void Ranges(void* arg, RangeFunction func);
-
- // -------------------------------------------------------------------
- // Control operations for getting and setting malloc implementation
- // specific parameters. Some currently useful properties:
- //
- // generic
- // -------
- // "generic.current_allocated_bytes"
- // Number of bytes currently allocated by application
- // This property is not writable.
- //
- // "generic.heap_size"
- // Number of bytes in the heap ==
- // current_allocated_bytes +
- // fragmentation +
- // freed memory regions
- // This property is not writable.
- //
- // tcmalloc
- // --------
- // "tcmalloc.max_total_thread_cache_bytes"
- // Upper limit on total number of bytes stored across all
- // per-thread caches. Default: 16MB.
- //
- // "tcmalloc.current_total_thread_cache_bytes"
- // Number of bytes used across all thread caches.
- // This property is not writable.
- //
- // "tcmalloc.central_cache_free_bytes"
- // Number of free bytes in the central cache that have been
- // assigned to size classes. They always count towards virtual
- // memory usage, and unless the underlying memory is swapped out
- // by the OS, they also count towards physical memory usage.
- // This property is not writable.
- //
- // "tcmalloc.transfer_cache_free_bytes"
- // Number of free bytes that are waiting to be transfered between
- // the central cache and a thread cache. They always count
- // towards virtual memory usage, and unless the underlying memory
- // is swapped out by the OS, they also count towards physical
- // memory usage. This property is not writable.
- //
- // "tcmalloc.thread_cache_free_bytes"
- // Number of free bytes in thread caches. They always count
- // towards virtual memory usage, and unless the underlying memory
- // is swapped out by the OS, they also count towards physical
- // memory usage. This property is not writable.
- //
- // "tcmalloc.pageheap_free_bytes"
- // Number of bytes in free, mapped pages in page heap. These
- // bytes can be used to fulfill allocation requests. They
- // always count towards virtual memory usage, and unless the
- // underlying memory is swapped out by the OS, they also count
- // towards physical memory usage. This property is not writable.
- //
- // "tcmalloc.pageheap_unmapped_bytes"
- // Number of bytes in free, unmapped pages in page heap.
- // These are bytes that have been released back to the OS,
- // possibly by one of the MallocExtension "Release" calls.
- // They can be used to fulfill allocation requests, but
- // typically incur a page fault. They always count towards
- // virtual memory usage, and depending on the OS, typically
- // do not count towards physical memory usage. This property
- // is not writable.
- // -------------------------------------------------------------------
-
- // Get the named "property"'s value. Returns true if the property
- // is known. Returns false if the property is not a valid property
- // name for the current malloc implementation.
- // REQUIRES: property != NULL; value != NULL
- virtual bool GetNumericProperty(const char* property, size_t* value);
-
- // Set the named "property"'s value. Returns true if the property
- // is known and writable. Returns false if the property is not a
- // valid property name for the current malloc implementation, or
- // is not writable.
- // REQUIRES: property != NULL
- virtual bool SetNumericProperty(const char* property, size_t value);
-
- // Mark the current thread as "idle". This routine may optionally
- // be called by threads as a hint to the malloc implementation that
- // any thread-specific resources should be released. Note: this may
- // be an expensive routine, so it should not be called too often.
- //
- // Also, if the code that calls this routine will go to sleep for
- // a while, it should take care to not allocate anything between
- // the call to this routine and the beginning of the sleep.
- //
- // Most malloc implementations ignore this routine.
- virtual void MarkThreadIdle();
-
- // Mark the current thread as "busy". This routine should be
- // called after MarkThreadIdle() if the thread will now do more
- // work. If this method is not called, performance may suffer.
- //
- // Most malloc implementations ignore this routine.
- virtual void MarkThreadBusy();
-
- // Gets the system allocator used by the malloc extension instance. Returns
- // NULL for malloc implementations that do not support pluggable system
- // allocators.
- virtual SysAllocator* GetSystemAllocator();
-
- // Sets the system allocator to the specified.
- //
- // Users could register their own system allocators for malloc implementation
- // that supports pluggable system allocators, such as TCMalloc, by doing:
- // alloc = new MyOwnSysAllocator();
- // MallocExtension::instance()->SetSystemAllocator(alloc);
- // It's up to users whether to fall back (recommended) to the default
- // system allocator (use GetSystemAllocator() above) or not. The caller is
- // responsible to any necessary locking.
- // See tcmalloc/system-alloc.h for the interface and
- // tcmalloc/memfs_malloc.cc for the examples.
- //
- // It's a no-op for malloc implementations that do not support pluggable
- // system allocators.
- virtual void SetSystemAllocator(SysAllocator *a);
-
- // Try to release num_bytes of free memory back to the operating
- // system for reuse. Use this extension with caution -- to get this
- // memory back may require faulting pages back in by the OS, and
- // that may be slow. (Currently only implemented in tcmalloc.)
- virtual void ReleaseToSystem(size_t num_bytes);
-
- // Same as ReleaseToSystem() but release as much memory as possible.
- virtual void ReleaseFreeMemory();
-
- // Sets the rate at which we release unused memory to the system.
- // Zero means we never release memory back to the system. Increase
- // this flag to return memory faster; decrease it to return memory
- // slower. Reasonable rates are in the range [0,10]. (Currently
- // only implemented in tcmalloc).
- virtual void SetMemoryReleaseRate(double rate);
-
- // Gets the release rate. Returns a value < 0 if unknown.
- virtual double GetMemoryReleaseRate();
-
- // Returns the estimated number of bytes that will be allocated for
- // a request of "size" bytes. This is an estimate: an allocation of
- // SIZE bytes may reserve more bytes, but will never reserve less.
- // (Currently only implemented in tcmalloc, other implementations
- // always return SIZE.)
- // This is equivalent to malloc_good_size() in OS X.
- virtual size_t GetEstimatedAllocatedSize(size_t size);
-
- // Returns the actual number N of bytes reserved by tcmalloc for the
- // pointer p. The client is allowed to use the range of bytes
- // [p, p+N) in any way it wishes (i.e. N is the "usable size" of this
- // allocation). This number may be equal to or greater than the number
- // of bytes requested when p was allocated.
- // p must have been allocated by this malloc implementation,
- // must not be an interior pointer -- that is, must be exactly
- // the pointer returned to by malloc() et al., not some offset
- // from that -- and should not have been freed yet. p may be NULL.
- // (Currently only implemented in tcmalloc; other implementations
- // will return 0.)
- // This is equivalent to malloc_size() in OS X, malloc_usable_size()
- // in glibc, and _msize() for windows.
- virtual size_t GetAllocatedSize(const 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();
-
- // Change the malloc implementation. Typically called by the
- // malloc implementation during initialization.
- static void Register(MallocExtension* implementation);
-
- // Returns detailed information about malloc's freelists. For each list,
- // return a FreeListInfo:
- struct FreeListInfo {
- size_t min_object_size;
- size_t max_object_size;
- size_t total_bytes_free;
- const char* type;
- };
- // Each item in the vector refers to a different freelist. The lists
- // are identified by the range of allocations that objects in the
- // list can satisfy ([min_object_size, max_object_size]) and the
- // type of freelist (see below). The current size of the list is
- // returned in total_bytes_free (which count against a processes
- // resident and virtual size).
- //
- // Currently supported types are:
- //
- // "tcmalloc.page{_unmapped}" - tcmalloc's page heap. An entry for each size
- // class in the page heap is returned. Bytes in "page_unmapped"
- // are no longer backed by physical memory and do not count against
- // the resident size of a process.
- //
- // "tcmalloc.large{_unmapped}" - tcmalloc's list of objects larger
- // than the largest page heap size class. Only one "large"
- // entry is returned. There is no upper-bound on the size
- // of objects in the large free list; this call returns
- // kint64max for max_object_size. Bytes in
- // "large_unmapped" are no longer backed by physical memory
- // and do not count against the resident size of a process.
- //
- // "tcmalloc.central" - tcmalloc's central free-list. One entry per
- // size-class is returned. Never unmapped.
- //
- // "debug.free_queue" - free objects queued by the debug allocator
- // and not returned to tcmalloc.
- //
- // "tcmalloc.thread" - tcmalloc's per-thread caches. Never unmapped.
- virtual void GetFreeListSizes(std::vector<FreeListInfo>* v);
-
- // Get a list of stack traces of sampled allocation points. Returns
- // a pointer to a "new[]-ed" result array, and stores the sample
- // period in "sample_period".
- //
- // The state is stored as a sequence of adjacent entries
- // in the returned array. Each entry has the following form:
- // uintptr_t count; // Number of objects with following trace
- // uintptr_t size; // Total size of objects with following trace
- // uintptr_t depth; // Number of PC values in stack trace
- // void* stack[depth]; // PC values that form the stack trace
- //
- // The list of entries is terminated by a "count" of 0.
- //
- // It is the responsibility of the caller to "delete[]" the returned array.
- //
- // May return NULL to indicate no results.
- //
- // This is an internal extension. Callers should use the more
- // convenient "GetHeapSample(string*)" method defined above.
- virtual void** ReadStackTraces(int* sample_period);
-
- // Like ReadStackTraces(), but returns stack traces that caused growth
- // in the address space size.
- virtual void** ReadHeapGrowthStackTraces();
-
- // Returns the size in bytes of the calling threads cache.
- virtual size_t GetThreadCacheSize();
-
- // Like MarkThreadIdle, but does not destroy the internal data
- // structures of the thread cache. When the thread resumes, it wil
- // have an empty cache but will not need to pay to reconstruct the
- // cache data structures.
- virtual void MarkThreadTemporarilyIdle();
-
- // Invokes func(arg, classinfo) for every size class.
- // *classinfo is filled in with information about the size class.
- typedef void (SizeClassFunction)(void*, const base::MallocSizeClass*);
- virtual void SizeClasses(void* arg, SizeClassFunction func);
-};
-
-namespace base {
-
-// Information passed per range. More fields may be added later.
-struct MallocRange {
- enum Type {
- INUSE, // Application is using this range
- FREE, // Range is currently free
- UNMAPPED, // Backing physical memory has been returned to the OS
- UNKNOWN
- // More enum values may be added in the future
- };
-
- uintptr_t address; // Address of range
- size_t length; // Byte length of range
- Type type; // Type of this range
- double fraction; // Fraction of range that is being used (0 if !INUSE)
-
- // Perhaps add the following:
- // - stack trace if this range was sampled
- // - heap growth stack trace if applicable to this range
- // - age when allocated (for inuse) or freed (if not in use)
-};
-
-struct MallocSizeClass {
- size_t bytes_per_obj;
- size_t pages_per_span;
- size_t num_spans;
- size_t num_thread_objs;
- size_t num_central_objs;
- size_t num_transfer_objs;
- size_t free_bytes;
- size_t alloc_bytes;
-};
-
-} // namespace base
-
-#endif // BASE_MALLOC_EXTENSION_H_
diff --git a/src/third_party/gperftools-2.5/src/gperftools/malloc_extension_c.h b/src/third_party/gperftools-2.5/src/gperftools/malloc_extension_c.h
deleted file mode 100644
index 70ff6868ecf..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/malloc_extension_c.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* 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: Craig Silverstein
- *
- * C shims for the C++ malloc_extension.h. See malloc_extension.h for
- * details. Note these C shims always work on
- * MallocExtension::instance(); it is not possible to have more than
- * one MallocExtension object in C applications.
- */
-
-#ifndef _MALLOC_EXTENSION_C_H_
-#define _MALLOC_EXTENSION_C_H_
-
-#include <stddef.h>
-#include <sys/types.h>
-
-/* Annoying stuff for windows -- makes sure clients can import these fns */
-#ifndef PERFTOOLS_DLL_DECL
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define kMallocExtensionHistogramSize 64
-
-PERFTOOLS_DLL_DECL int MallocExtension_VerifyAllMemory(void);
-PERFTOOLS_DLL_DECL int MallocExtension_VerifyNewMemory(const void* p);
-PERFTOOLS_DLL_DECL int MallocExtension_VerifyArrayNewMemory(const void* p);
-PERFTOOLS_DLL_DECL int MallocExtension_VerifyMallocMemory(const void* p);
-PERFTOOLS_DLL_DECL int MallocExtension_MallocMemoryStats(int* blocks, size_t* total,
- int histogram[kMallocExtensionHistogramSize]);
-PERFTOOLS_DLL_DECL void MallocExtension_GetStats(char* buffer, int buffer_length);
-
-/* TODO(csilvers): write a C version of these routines, that perhaps
- * takes a function ptr and a void *.
- */
-/* void MallocExtension_GetHeapSample(string* result); */
-/* void MallocExtension_GetHeapGrowthStacks(string* result); */
-
-PERFTOOLS_DLL_DECL int MallocExtension_GetNumericProperty(const char* property, size_t* value);
-PERFTOOLS_DLL_DECL int MallocExtension_SetNumericProperty(const char* property, size_t value);
-PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadIdle(void);
-PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadBusy(void);
-PERFTOOLS_DLL_DECL void MallocExtension_ReleaseToSystem(size_t num_bytes);
-PERFTOOLS_DLL_DECL void MallocExtension_ReleaseFreeMemory(void);
-PERFTOOLS_DLL_DECL size_t MallocExtension_GetEstimatedAllocatedSize(size_t size);
-PERFTOOLS_DLL_DECL size_t MallocExtension_GetAllocatedSize(const void* p);
-PERFTOOLS_DLL_DECL size_t MallocExtension_GetThreadCacheSize(void);
-PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadTemporarilyIdle(void);
-
-/*
- * 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
-
-#endif /* _MALLOC_EXTENSION_C_H_ */
diff --git a/src/third_party/gperftools-2.5/src/gperftools/malloc_hook.h b/src/third_party/gperftools-2.5/src/gperftools/malloc_hook.h
deleted file mode 100644
index b76411fb590..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/malloc_hook.h
+++ /dev/null
@@ -1,359 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-//
-// Some of our malloc implementations can invoke the following hooks whenever
-// memory is allocated or deallocated. MallocHook is thread-safe, and things
-// you do before calling AddFooHook(MyHook) are visible to any resulting calls
-// to MyHook. Hooks must be thread-safe. If you write:
-//
-// CHECK(MallocHook::AddNewHook(&MyNewHook));
-//
-// MyNewHook will be invoked in subsequent calls in the current thread, but
-// there are no guarantees on when it might be invoked in other threads.
-//
-// There are a limited number of slots available for each hook type. Add*Hook
-// will return false if there are no slots available. Remove*Hook will return
-// false if the given hook was not already installed.
-//
-// The order in which individual hooks are called in Invoke*Hook is undefined.
-//
-// It is safe for a hook to remove itself within Invoke*Hook and add other
-// hooks. Any hooks added inside a hook invocation (for the same hook type)
-// will not be invoked for the current invocation.
-//
-// One important user of these hooks is the heap profiler.
-//
-// CAVEAT: If you add new MallocHook::Invoke* calls then those calls must be
-// directly in the code of the (de)allocation function that is provided to the
-// user and that function must have an ATTRIBUTE_SECTION(malloc_hook) attribute.
-//
-// Note: the Invoke*Hook() functions are defined in malloc_hook-inl.h. If you
-// need to invoke a hook (which you shouldn't unless you're part of tcmalloc),
-// be sure to #include malloc_hook-inl.h in addition to malloc_hook.h.
-//
-// NOTE FOR C USERS: If you want to use malloc_hook functionality from
-// a C program, #include malloc_hook_c.h instead of this file.
-
-#ifndef _MALLOC_HOOK_H_
-#define _MALLOC_HOOK_H_
-
-#include <stddef.h>
-#include <sys/types.h>
-extern "C" {
-#include "malloc_hook_c.h" // a C version of the malloc_hook interface
-}
-
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef PERFTOOLS_DLL_DECL
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# 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
-// for details of these types/functions.
-
-class PERFTOOLS_DLL_DECL MallocHook {
- public:
- // The NewHook is invoked whenever an object is allocated.
- // It may be passed NULL if the allocator returned NULL.
- typedef MallocHook_NewHook NewHook;
- inline static bool AddNewHook(NewHook hook) {
- return MallocHook_AddNewHook(hook);
- }
- inline static bool RemoveNewHook(NewHook hook) {
- return MallocHook_RemoveNewHook(hook);
- }
- inline static void InvokeNewHook(const void* p, size_t s);
-
- // The DeleteHook is invoked whenever an object is deallocated.
- // It may be passed NULL if the caller is trying to delete NULL.
- typedef MallocHook_DeleteHook DeleteHook;
- inline static bool AddDeleteHook(DeleteHook hook) {
- return MallocHook_AddDeleteHook(hook);
- }
- inline static bool RemoveDeleteHook(DeleteHook hook) {
- return MallocHook_RemoveDeleteHook(hook);
- }
- inline static void InvokeDeleteHook(const void* p);
-
- // The PreMmapHook is invoked with mmap or mmap64 arguments just
- // before the call is actually made. Such a hook may be useful
- // in memory limited contexts, to catch allocations that will exceed
- // a memory limit, and take outside actions to increase that limit.
- typedef MallocHook_PreMmapHook PreMmapHook;
- inline static bool AddPreMmapHook(PreMmapHook hook) {
- return MallocHook_AddPreMmapHook(hook);
- }
- inline static bool RemovePreMmapHook(PreMmapHook hook) {
- return MallocHook_RemovePreMmapHook(hook);
- }
- inline static void InvokePreMmapHook(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset);
-
- // The MmapReplacement is invoked after the PreMmapHook but before
- // the call is actually made. The MmapReplacement should return true
- // if it handled the call, or false if it is still necessary to
- // call mmap/mmap64.
- // This should be used only by experts, and users must be be
- // extremely careful to avoid recursive calls to mmap. The replacement
- // should be async signal safe.
- // Only one MmapReplacement is supported. After setting an MmapReplacement
- // you must call RemoveMmapReplacement before calling SetMmapReplacement
- // again.
- typedef MallocHook_MmapReplacement MmapReplacement;
- inline static bool SetMmapReplacement(MmapReplacement hook) {
- return MallocHook_SetMmapReplacement(hook);
- }
- inline static bool RemoveMmapReplacement(MmapReplacement hook) {
- return MallocHook_RemoveMmapReplacement(hook);
- }
- inline static bool InvokeMmapReplacement(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset,
- void** result);
-
-
- // The MmapHook is invoked whenever a region of memory is mapped.
- // It may be passed MAP_FAILED if the mmap failed.
- typedef MallocHook_MmapHook MmapHook;
- inline static bool AddMmapHook(MmapHook hook) {
- return MallocHook_AddMmapHook(hook);
- }
- inline static bool RemoveMmapHook(MmapHook hook) {
- return MallocHook_RemoveMmapHook(hook);
- }
- inline static void InvokeMmapHook(const void* result,
- const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset);
-
- // The MunmapReplacement is invoked with munmap arguments just before
- // the call is actually made. The MunmapReplacement should return true
- // if it handled the call, or false if it is still necessary to
- // call munmap.
- // This should be used only by experts. The replacement should be
- // async signal safe.
- // Only one MunmapReplacement is supported. After setting an
- // MunmapReplacement you must call RemoveMunmapReplacement before
- // calling SetMunmapReplacement again.
- typedef MallocHook_MunmapReplacement MunmapReplacement;
- inline static bool SetMunmapReplacement(MunmapReplacement hook) {
- return MallocHook_SetMunmapReplacement(hook);
- }
- inline static bool RemoveMunmapReplacement(MunmapReplacement hook) {
- return MallocHook_RemoveMunmapReplacement(hook);
- }
- inline static bool InvokeMunmapReplacement(const void* p,
- size_t size,
- int* result);
-
- // The MunmapHook is invoked whenever a region of memory is unmapped.
- typedef MallocHook_MunmapHook MunmapHook;
- inline static bool AddMunmapHook(MunmapHook hook) {
- return MallocHook_AddMunmapHook(hook);
- }
- inline static bool RemoveMunmapHook(MunmapHook hook) {
- return MallocHook_RemoveMunmapHook(hook);
- }
- inline static void InvokeMunmapHook(const void* p, size_t size);
-
- // The MremapHook is invoked whenever a region of memory is remapped.
- typedef MallocHook_MremapHook MremapHook;
- inline static bool AddMremapHook(MremapHook hook) {
- return MallocHook_AddMremapHook(hook);
- }
- inline static bool RemoveMremapHook(MremapHook hook) {
- return MallocHook_RemoveMremapHook(hook);
- }
- inline static void InvokeMremapHook(const void* result,
- const void* old_addr,
- size_t old_size,
- size_t new_size,
- int flags,
- const void* new_addr);
-
- // The PreSbrkHook is invoked just before sbrk is called -- except when
- // the increment is 0. This is because sbrk(0) is often called
- // to get the top of the memory stack, and is not actually a
- // memory-allocation call. It may be useful in memory-limited contexts,
- // to catch allocations that will exceed the limit and take outside
- // actions to increase such a limit.
- typedef MallocHook_PreSbrkHook PreSbrkHook;
- inline static bool AddPreSbrkHook(PreSbrkHook hook) {
- return MallocHook_AddPreSbrkHook(hook);
- }
- inline static bool RemovePreSbrkHook(PreSbrkHook hook) {
- return MallocHook_RemovePreSbrkHook(hook);
- }
- inline static void InvokePreSbrkHook(ptrdiff_t increment);
-
- // The SbrkHook is invoked whenever sbrk is called -- except when
- // the increment is 0. This is because sbrk(0) is often called
- // to get the top of the memory stack, and is not actually a
- // memory-allocation call.
- typedef MallocHook_SbrkHook SbrkHook;
- inline static bool AddSbrkHook(SbrkHook hook) {
- return MallocHook_AddSbrkHook(hook);
- }
- inline static bool RemoveSbrkHook(SbrkHook hook) {
- return MallocHook_RemoveSbrkHook(hook);
- }
- inline static void InvokeSbrkHook(const void* result, ptrdiff_t increment);
-
- // Get the current stack trace. Try to skip all routines up to and
- // and including the caller of MallocHook::Invoke*.
- // Use "skip_count" (similarly to GetStackTrace from stacktrace.h)
- // as a hint about how many routines to skip if better information
- // is not available.
- inline static int GetCallerStackTrace(void** result, int max_depth,
- int skip_count) {
- return MallocHook_GetCallerStackTrace(result, max_depth, skip_count);
- }
-
- // Unhooked versions of mmap() and munmap(). These should be used
- // only by experts, since they bypass heapchecking, etc.
- // Note: These do not run hooks, but they still use the MmapReplacement
- // and MunmapReplacement.
- static void* UnhookedMMap(void *start, size_t length, int prot, int flags,
- int fd, off_t offset);
- static int UnhookedMUnmap(void *start, size_t length);
-
- // The following are DEPRECATED.
- inline static NewHook GetNewHook();
- inline static NewHook SetNewHook(NewHook hook) {
- return MallocHook_SetNewHook(hook);
- }
-
- inline static DeleteHook GetDeleteHook();
- inline static DeleteHook SetDeleteHook(DeleteHook hook) {
- return MallocHook_SetDeleteHook(hook);
- }
-
- inline static PreMmapHook GetPreMmapHook();
- inline static PreMmapHook SetPreMmapHook(PreMmapHook hook) {
- return MallocHook_SetPreMmapHook(hook);
- }
-
- inline static MmapHook GetMmapHook();
- inline static MmapHook SetMmapHook(MmapHook hook) {
- return MallocHook_SetMmapHook(hook);
- }
-
- inline static MunmapHook GetMunmapHook();
- inline static MunmapHook SetMunmapHook(MunmapHook hook) {
- return MallocHook_SetMunmapHook(hook);
- }
-
- inline static MremapHook GetMremapHook();
- inline static MremapHook SetMremapHook(MremapHook hook) {
- return MallocHook_SetMremapHook(hook);
- }
-
- inline static PreSbrkHook GetPreSbrkHook();
- inline static PreSbrkHook SetPreSbrkHook(PreSbrkHook hook) {
- return MallocHook_SetPreSbrkHook(hook);
- }
-
- inline static SbrkHook GetSbrkHook();
- inline static SbrkHook SetSbrkHook(SbrkHook hook) {
- return MallocHook_SetSbrkHook(hook);
- }
- // End of DEPRECATED methods.
-
- private:
- // Slow path versions of Invoke*Hook.
- static void InvokeNewHookSlow(const void* p, size_t s);
- static void InvokeDeleteHookSlow(const void* p);
- static void InvokePreMmapHookSlow(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset);
- static void InvokeMmapHookSlow(const void* result,
- const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset);
- static bool InvokeMmapReplacementSlow(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset,
- void** result);
- static void InvokeMunmapHookSlow(const void* p, size_t size);
- static bool InvokeMunmapReplacementSlow(const void* p,
- size_t size,
- int* result);
- static void InvokeMremapHookSlow(const void* result,
- const void* old_addr,
- size_t old_size,
- size_t new_size,
- int flags,
- const void* new_addr);
- static void InvokePreSbrkHookSlow(ptrdiff_t increment);
- static void InvokeSbrkHookSlow(const void* result, ptrdiff_t increment);
-};
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-
-#endif /* _MALLOC_HOOK_H_ */
diff --git a/src/third_party/gperftools-2.5/src/gperftools/malloc_hook_c.h b/src/third_party/gperftools-2.5/src/gperftools/malloc_hook_c.h
deleted file mode 100644
index 56337e15e83..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/malloc_hook_c.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/* 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: Craig Silverstein
- *
- * C shims for the C++ malloc_hook.h. See malloc_hook.h for details
- * on how to use these.
- */
-
-#ifndef _MALLOC_HOOK_C_H_
-#define _MALLOC_HOOK_C_H_
-
-#include <stddef.h>
-#include <sys/types.h>
-
-/* Annoying stuff for windows; makes sure clients can import these functions */
-#ifndef PERFTOOLS_DLL_DECL
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Get the current stack trace. Try to skip all routines up to and
- * and including the caller of MallocHook::Invoke*.
- * Use "skip_count" (similarly to GetStackTrace from stacktrace.h)
- * as a hint about how many routines to skip if better information
- * is not available.
- */
-PERFTOOLS_DLL_DECL
-int MallocHook_GetCallerStackTrace(void** result, int max_depth,
- int skip_count);
-
-/* The MallocHook_{Add,Remove}*Hook functions return 1 on success and 0 on
- * failure.
- */
-
-typedef void (*MallocHook_NewHook)(const void* ptr, size_t size);
-PERFTOOLS_DLL_DECL
-int MallocHook_AddNewHook(MallocHook_NewHook hook);
-PERFTOOLS_DLL_DECL
-int MallocHook_RemoveNewHook(MallocHook_NewHook hook);
-
-typedef void (*MallocHook_DeleteHook)(const void* ptr);
-PERFTOOLS_DLL_DECL
-int MallocHook_AddDeleteHook(MallocHook_DeleteHook hook);
-PERFTOOLS_DLL_DECL
-int MallocHook_RemoveDeleteHook(MallocHook_DeleteHook hook);
-
-typedef void (*MallocHook_PreMmapHook)(const void *start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset);
-PERFTOOLS_DLL_DECL
-int MallocHook_AddPreMmapHook(MallocHook_PreMmapHook hook);
-PERFTOOLS_DLL_DECL
-int MallocHook_RemovePreMmapHook(MallocHook_PreMmapHook hook);
-
-typedef void (*MallocHook_MmapHook)(const void* result,
- const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset);
-PERFTOOLS_DLL_DECL
-int MallocHook_AddMmapHook(MallocHook_MmapHook hook);
-PERFTOOLS_DLL_DECL
-int MallocHook_RemoveMmapHook(MallocHook_MmapHook hook);
-
-typedef int (*MallocHook_MmapReplacement)(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset,
- void** result);
-int MallocHook_SetMmapReplacement(MallocHook_MmapReplacement hook);
-int MallocHook_RemoveMmapReplacement(MallocHook_MmapReplacement hook);
-
-typedef void (*MallocHook_MunmapHook)(const void* ptr, size_t size);
-PERFTOOLS_DLL_DECL
-int MallocHook_AddMunmapHook(MallocHook_MunmapHook hook);
-PERFTOOLS_DLL_DECL
-int MallocHook_RemoveMunmapHook(MallocHook_MunmapHook hook);
-
-typedef int (*MallocHook_MunmapReplacement)(const void* ptr,
- size_t size,
- int* result);
-int MallocHook_SetMunmapReplacement(MallocHook_MunmapReplacement hook);
-int MallocHook_RemoveMunmapReplacement(MallocHook_MunmapReplacement hook);
-
-typedef void (*MallocHook_MremapHook)(const void* result,
- const void* old_addr,
- size_t old_size,
- size_t new_size,
- int flags,
- const void* new_addr);
-PERFTOOLS_DLL_DECL
-int MallocHook_AddMremapHook(MallocHook_MremapHook hook);
-PERFTOOLS_DLL_DECL
-int MallocHook_RemoveMremapHook(MallocHook_MremapHook hook);
-
-typedef void (*MallocHook_PreSbrkHook)(ptrdiff_t increment);
-PERFTOOLS_DLL_DECL
-int MallocHook_AddPreSbrkHook(MallocHook_PreSbrkHook hook);
-PERFTOOLS_DLL_DECL
-int MallocHook_RemovePreSbrkHook(MallocHook_PreSbrkHook hook);
-
-typedef void (*MallocHook_SbrkHook)(const void* result, ptrdiff_t increment);
-PERFTOOLS_DLL_DECL
-int MallocHook_AddSbrkHook(MallocHook_SbrkHook hook);
-PERFTOOLS_DLL_DECL
-int MallocHook_RemoveSbrkHook(MallocHook_SbrkHook hook);
-
-/* The following are DEPRECATED. */
-PERFTOOLS_DLL_DECL
-MallocHook_NewHook MallocHook_SetNewHook(MallocHook_NewHook hook);
-PERFTOOLS_DLL_DECL
-MallocHook_DeleteHook MallocHook_SetDeleteHook(MallocHook_DeleteHook hook);
-PERFTOOLS_DLL_DECL
-MallocHook_PreMmapHook MallocHook_SetPreMmapHook(MallocHook_PreMmapHook hook);
-PERFTOOLS_DLL_DECL
-MallocHook_MmapHook MallocHook_SetMmapHook(MallocHook_MmapHook hook);
-PERFTOOLS_DLL_DECL
-MallocHook_MunmapHook MallocHook_SetMunmapHook(MallocHook_MunmapHook hook);
-PERFTOOLS_DLL_DECL
-MallocHook_MremapHook MallocHook_SetMremapHook(MallocHook_MremapHook hook);
-PERFTOOLS_DLL_DECL
-MallocHook_PreSbrkHook MallocHook_SetPreSbrkHook(MallocHook_PreSbrkHook hook);
-PERFTOOLS_DLL_DECL
-MallocHook_SbrkHook MallocHook_SetSbrkHook(MallocHook_SbrkHook hook);
-/* End of DEPRECATED functions. */
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* _MALLOC_HOOK_C_H_ */
diff --git a/src/third_party/gperftools-2.5/src/gperftools/profiler.h b/src/third_party/gperftools-2.5/src/gperftools/profiler.h
deleted file mode 100644
index 2d272d616a9..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/profiler.h
+++ /dev/null
@@ -1,169 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* 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
- *
- * Module for CPU profiling based on periodic pc-sampling.
- *
- * For full(er) information, see doc/cpuprofile.html
- *
- * This module is linked into your program with
- * no slowdown caused by this unless you activate the profiler
- * using one of the following methods:
- *
- * 1. Before starting the program, set the environment variable
- * "CPUPROFILE" to be the name of the file to which the profile
- * data should be written.
- *
- * 2. Programmatically, start and stop the profiler using the
- * routines "ProfilerStart(filename)" and "ProfilerStop()".
- *
- *
- * (Note: if using linux 2.4 or earlier, only the main thread may be
- * profiled.)
- *
- * Use pprof to view the resulting profile output.
- * % pprof <path_to_executable> <profile_file_name>
- * % pprof --gv <path_to_executable> <profile_file_name>
- *
- * These functions are thread-safe.
- */
-
-#ifndef BASE_PROFILER_H_
-#define BASE_PROFILER_H_
-
-#include <time.h> /* For time_t */
-
-/* Annoying stuff for windows; makes sure clients can import these functions */
-#ifndef PERFTOOLS_DLL_DECL
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-/* All this code should be usable from within C apps. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Profiler options, for use with ProfilerStartWithOptions. To use:
- *
- * struct ProfilerOptions options;
- * memset(&options, 0, sizeof options);
- *
- * then fill in fields as needed.
- *
- * This structure is intended to be usable from C code, so no constructor
- * is provided to initialize it. (Use memset as described above).
- */
-struct ProfilerOptions {
- /* Filter function and argument.
- *
- * If filter_in_thread is not NULL, when a profiling tick is delivered
- * the profiler will call:
- *
- * (*filter_in_thread)(filter_in_thread_arg)
- *
- * If it returns nonzero, the sample will be included in the profile.
- * Note that filter_in_thread runs in a signal handler, so must be
- * async-signal-safe.
- *
- * A typical use would be to set up filter results for each thread
- * in the system before starting the profiler, then to make
- * filter_in_thread be a very simple function which retrieves those
- * results in an async-signal-safe way. Retrieval could be done
- * using thread-specific data, or using a shared data structure that
- * supports async-signal-safe lookups.
- */
- int (*filter_in_thread)(void *arg);
- void *filter_in_thread_arg;
-};
-
-/* Start profiling and write profile info into fname, discarding any
- * existing profiling data in that file.
- *
- * This is equivalent to calling ProfilerStartWithOptions(fname, NULL).
- */
-PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname);
-
-/* Start profiling and write profile into fname, discarding any
- * existing profiling data in that file.
- *
- * The profiler is configured using the options given by 'options'.
- * Options which are not specified are given default values.
- *
- * 'options' may be NULL, in which case all are given default values.
- *
- * Returns nonzero if profiling was started successfully, or zero else.
- */
-PERFTOOLS_DLL_DECL int ProfilerStartWithOptions(
- const char *fname, const struct ProfilerOptions *options);
-
-/* Stop profiling. Can be started again with ProfilerStart(), but
- * the currently accumulated profiling data will be cleared.
- */
-PERFTOOLS_DLL_DECL void ProfilerStop(void);
-
-/* Flush any currently buffered profiling state to the profile file.
- * Has no effect if the profiler has not been started.
- */
-PERFTOOLS_DLL_DECL void ProfilerFlush(void);
-
-
-/* DEPRECATED: these functions were used to enable/disable profiling
- * in the current thread, but no longer do anything.
- */
-PERFTOOLS_DLL_DECL void ProfilerEnable(void);
-PERFTOOLS_DLL_DECL void ProfilerDisable(void);
-
-/* Returns nonzero if profile is currently enabled, zero if it's not. */
-PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads(void);
-
-/* Routine for registering new threads with the profiler.
- */
-PERFTOOLS_DLL_DECL void ProfilerRegisterThread(void);
-
-/* Stores state about profiler's current status into "*state". */
-struct ProfilerState {
- int enabled; /* Is profiling currently enabled? */
- time_t start_time; /* If enabled, when was profiling started? */
- char profile_name[1024]; /* Name of profile file being written, or '\0' */
- int samples_gathered; /* Number of samples gathered so far (or 0) */
-};
-PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(struct ProfilerState* state);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* BASE_PROFILER_H_ */
diff --git a/src/third_party/gperftools-2.5/src/gperftools/stacktrace.h b/src/third_party/gperftools-2.5/src/gperftools/stacktrace.h
deleted file mode 100644
index 2b9c5a13209..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/stacktrace.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-//
-// Routines to extract the current stack trace. These functions are
-// thread-safe.
-
-#ifndef GOOGLE_STACKTRACE_H_
-#define GOOGLE_STACKTRACE_H_
-
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef PERFTOOLS_DLL_DECL
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-
-// Skips the most recent "skip_count" stack frames (also skips the
-// frame generated for the "GetStackFrames" routine itself), and then
-// records the pc values for up to the next "max_depth" frames in
-// "result", and the corresponding stack frame sizes in "sizes".
-// Returns the number of values recorded in "result"/"sizes".
-//
-// Example:
-// main() { foo(); }
-// foo() { bar(); }
-// bar() {
-// void* result[10];
-// int sizes[10];
-// int depth = GetStackFrames(result, sizes, 10, 1);
-// }
-//
-// The GetStackFrames call will skip the frame for "bar". It will
-// return 2 and will produce pc values that map to the following
-// procedures:
-// result[0] foo
-// result[1] main
-// (Actually, there may be a few more entries after "main" to account for
-// startup procedures.)
-// And corresponding stack frame sizes will also be recorded:
-// sizes[0] 16
-// sizes[1] 16
-// (Stack frame sizes of 16 above are just for illustration purposes.)
-// Stack frame sizes of 0 or less indicate that those frame sizes couldn't
-// be identified.
-//
-// This routine may return fewer stack frame entries than are
-// available. Also note that "result" and "sizes" must both be non-NULL.
-extern PERFTOOLS_DLL_DECL int GetStackFrames(void** result, int* sizes, int max_depth,
- int skip_count);
-
-// Same as above, but to be used from a signal handler. The "uc" parameter
-// should be the pointer to ucontext_t which was passed as the 3rd parameter
-// to sa_sigaction signal handler. It may help the unwinder to get a
-// better stack trace under certain conditions. The "uc" may safely be NULL.
-extern PERFTOOLS_DLL_DECL int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
- int skip_count, const void *uc);
-
-// This is similar to the GetStackFrames routine, except that it returns
-// the stack trace only, and not the stack frame sizes as well.
-// Example:
-// main() { foo(); }
-// foo() { bar(); }
-// bar() {
-// void* result[10];
-// int depth = GetStackTrace(result, 10, 1);
-// }
-//
-// This produces:
-// result[0] foo
-// result[1] main
-// .... ...
-//
-// "result" must not be NULL.
-extern PERFTOOLS_DLL_DECL int GetStackTrace(void** result, int max_depth,
- int skip_count);
-
-// Same as above, but to be used from a signal handler. The "uc" parameter
-// should be the pointer to ucontext_t which was passed as the 3rd parameter
-// to sa_sigaction signal handler. It may help the unwinder to get a
-// better stack trace under certain conditions. The "uc" may safely be NULL.
-extern PERFTOOLS_DLL_DECL int GetStackTraceWithContext(void** result, int max_depth,
- int skip_count, const void *uc);
-
-#endif /* GOOGLE_STACKTRACE_H_ */
diff --git a/src/third_party/gperftools-2.5/src/gperftools/t1.sh b/src/third_party/gperftools-2.5/src/gperftools/t1.sh
deleted file mode 100644
index c66e7c95a4d..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/t1.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-
-TCMALLOC_H=tcmalloc.h
-TCMALLOC_H_TMP=tcmalloc.h.bak
-for line_number in $(grep -n "@ac_cv_have_struct_mallinfo@" tcmalloc.h.in | cut -d: -f1) ; do
- sed "${line_number}s/.*/#ifdef HAVE_STRUCT_MALLINFO/" < $TCMALLOC_H > $TCMALLOC_H_TMP
- cp $TCMALLOC_H_TMP $TCMALLOC_H
-done
-
diff --git a/src/third_party/gperftools-2.5/src/gperftools/tcmalloc.h b/src/third_party/gperftools-2.5/src/gperftools/tcmalloc.h
deleted file mode 100644
index 4f5cbc420bc..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/tcmalloc.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2003, 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>
- * .h file by Craig Silverstein <opensource@google.com>
- */
-
-#ifndef TCMALLOC_TCMALLOC_H_
-#define TCMALLOC_TCMALLOC_H_
-
-#include <stddef.h> /* for size_t */
-
-/* Define the version number so folks can check against it */
-#define TC_VERSION_MAJOR 2
-#define TC_VERSION_MINOR 5
-#define TC_VERSION_PATCH ""
-#define TC_VERSION_STRING "gperftools 2.5"
-
-/* For struct mallinfo, if it's defined. */
-#ifdef HAVE_STRUCT_MALLINFO
-# include <malloc.h>
-#endif
-
-#ifdef __cplusplus
-#define PERFTOOLS_THROW noexcept
-#else
-# ifdef __GNUC__
-# define PERFTOOLS_THROW __attribute__((__nothrow__))
-# else
-# define PERFTOOLS_THROW
-# endif
-#endif
-
-#ifndef PERFTOOLS_DLL_DECL
-#define PERFTOOLS_DLL_DECL_DEFINED
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-#ifdef __cplusplus
-namespace std {
-struct nothrow_t;
-}
-
-extern "C" {
-#endif
- /*
- * Returns a human-readable version string. If major, minor,
- * and/or patch are not NULL, they are set to the major version,
- * minor version, and patch-code (a string, usually "").
- */
- PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor,
- const char** patch) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
- size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
- size_t align, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_THROW;
-#ifdef HAVE_STRUCT_MALLINFO
- PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_THROW;
-#endif
-
- /*
- * This is an alias for MallocExtension::instance()->GetAllocatedSize().
- * It is equivalent to
- * OS X: malloc_size()
- * glibc: malloc_usable_size()
- * Windows: _msize()
- */
- PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_THROW;
-
-#ifdef __cplusplus
- PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_new(size_t size);
- PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
- PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
-}
-#endif
-
-/* We're only un-defining those for public */
-#if !defined(GPERFTOOLS_CONFIG_H_)
-
-#undef PERFTOOLS_THROW
-
-#ifdef PERFTOOLS_DLL_DECL_DEFINED
-#undef PERFTOOLS_DLL_DECL
-#undef PERFTOOLS_DLL_DECL_DEFINED
-#endif
-
-#endif /* GPERFTOOLS_CONFIG_H_ */
-
-#endif /* #ifndef TCMALLOC_TCMALLOC_H_ */
diff --git a/src/third_party/gperftools-2.5/src/gperftools/tcmalloc.h.in b/src/third_party/gperftools-2.5/src/gperftools/tcmalloc.h.in
deleted file mode 100644
index adf04b437ec..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/tcmalloc.h.in
+++ /dev/null
@@ -1,147 +0,0 @@
-// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2003, 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>
- * .h file by Craig Silverstein <opensource@google.com>
- */
-
-#ifndef TCMALLOC_TCMALLOC_H_
-#define TCMALLOC_TCMALLOC_H_
-
-#include <stddef.h> /* for size_t */
-
-/* Define the version number so folks can check against it */
-#define TC_VERSION_MAJOR @TC_VERSION_MAJOR@
-#define TC_VERSION_MINOR @TC_VERSION_MINOR@
-#define TC_VERSION_PATCH "@TC_VERSION_PATCH@"
-#define TC_VERSION_STRING "gperftools @TC_VERSION_MAJOR@.@TC_VERSION_MINOR@@TC_VERSION_PATCH@"
-
-/* For struct mallinfo, if it's defined. */
-#if @ac_cv_have_struct_mallinfo@
-# include <malloc.h>
-#endif
-
-#ifdef __cplusplus
-#define PERFTOOLS_THROW throw()
-#else
-# ifdef __GNUC__
-# define PERFTOOLS_THROW __attribute__((__nothrow__))
-# else
-# define PERFTOOLS_THROW
-# endif
-#endif
-
-#ifndef PERFTOOLS_DLL_DECL
-#define PERFTOOLS_DLL_DECL_DEFINED
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-#ifdef __cplusplus
-namespace std {
-struct nothrow_t;
-}
-
-extern "C" {
-#endif
- /*
- * Returns a human-readable version string. If major, minor,
- * and/or patch are not NULL, they are set to the major version,
- * minor version, and patch-code (a string, usually "").
- */
- PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor,
- const char** patch) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
- size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
- size_t align, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_THROW;
-#if @ac_cv_have_struct_mallinfo@
- PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_THROW;
-#endif
-
- /*
- * This is an alias for MallocExtension::instance()->GetAllocatedSize().
- * It is equivalent to
- * OS X: malloc_size()
- * glibc: malloc_usable_size()
- * Windows: _msize()
- */
- PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_THROW;
-
-#ifdef __cplusplus
- PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_new(size_t size);
- PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
- PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
-}
-#endif
-
-/* We're only un-defining those for public */
-#if !defined(GPERFTOOLS_CONFIG_H_)
-
-#undef PERFTOOLS_THROW
-
-#ifdef PERFTOOLS_DLL_DECL_DEFINED
-#undef PERFTOOLS_DLL_DECL
-#undef PERFTOOLS_DLL_DECL_DEFINED
-#endif
-
-#endif /* GPERFTOOLS_CONFIG_H_ */
-
-#endif /* #ifndef TCMALLOC_TCMALLOC_H_ */
diff --git a/src/third_party/gperftools-2.5/src/gperftools/tcmalloc.hbak b/src/third_party/gperftools-2.5/src/gperftools/tcmalloc.hbak
deleted file mode 100644
index ebb59af8472..00000000000
--- a/src/third_party/gperftools-2.5/src/gperftools/tcmalloc.hbak
+++ /dev/null
@@ -1,147 +0,0 @@
-// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2003, 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>
- * .h file by Craig Silverstein <opensource@google.com>
- */
-
-#ifndef TCMALLOC_TCMALLOC_H_
-#define TCMALLOC_TCMALLOC_H_
-
-#include <stddef.h> /* for size_t */
-
-/* Define the version number so folks can check against it */
-#define TC_VERSION_MAJOR 2
-#define TC_VERSION_MINOR 5
-#define TC_VERSION_PATCH ""
-#define TC_VERSION_STRING "gperftools 2.5"
-
-/* For struct mallinfo, if it's defined. */
-#if HAVE_STRUCT_MALLINFO
-# include <malloc.h>
-#endif
-
-#ifdef __cplusplus
-#define PERFTOOLS_THROW throw()
-#else
-# ifdef __GNUC__
-# define PERFTOOLS_THROW __attribute__((__nothrow__))
-# else
-# define PERFTOOLS_THROW
-# endif
-#endif
-
-#ifndef PERFTOOLS_DLL_DECL
-#define PERFTOOLS_DLL_DECL_DEFINED
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-#ifdef __cplusplus
-namespace std {
-struct nothrow_t;
-}
-
-extern "C" {
-#endif
- /*
- * Returns a human-readable version string. If major, minor,
- * and/or patch are not NULL, they are set to the major version,
- * minor version, and patch-code (a string, usually "").
- */
- PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor,
- const char** patch) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
- size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
- size_t align, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_THROW;
-#if HAVE_STRUCT_MALLINFO
- PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_THROW;
-#endif
-
- /*
- * This is an alias for MallocExtension::instance()->GetAllocatedSize().
- * It is equivalent to
- * OS X: malloc_size()
- * glibc: malloc_usable_size()
- * Windows: _msize()
- */
- PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_THROW;
-
-#ifdef __cplusplus
- PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_new(size_t size);
- PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
- PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
-}
-#endif
-
-/* We're only un-defining those for public */
-#if !defined(GPERFTOOLS_CONFIG_H_)
-
-#undef PERFTOOLS_THROW
-
-#ifdef PERFTOOLS_DLL_DECL_DEFINED
-#undef PERFTOOLS_DLL_DECL
-#undef PERFTOOLS_DLL_DECL_DEFINED
-#endif
-
-#endif /* GPERFTOOLS_CONFIG_H_ */
-
-#endif /* #ifndef TCMALLOC_TCMALLOC_H_ */
diff --git a/src/third_party/gperftools-2.5/src/heap-checker-bcad.cc b/src/third_party/gperftools-2.5/src/heap-checker-bcad.cc
deleted file mode 100644
index 00efdb7cfd4..00000000000
--- a/src/third_party/gperftools-2.5/src/heap-checker-bcad.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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.
-
-// ---
-// All Rights Reserved.
-//
-// Author: Maxim Lifantsev
-//
-// A file to ensure that components of heap leak checker run before
-// all global object constructors and after all global object
-// destructors.
-//
-// This file must be the last library any binary links against.
-// Otherwise, the heap checker may not be able to run early enough to
-// catalog all the global objects in your program. If this happens,
-// and later in the program you allocate memory and have one of these
-// "uncataloged" global objects point to it, the heap checker will
-// consider that allocation to be a leak, even though it's not (since
-// the allocated object is reachable from global data and hence "live").
-
-#include <stdlib.h> // for abort()
-#include <gperftools/malloc_extension.h>
-
-// A dummy variable to refer from heap-checker.cc. This is to make
-// sure this file is not optimized out by the linker.
-bool heap_leak_checker_bcad_variable;
-
-extern void HeapLeakChecker_AfterDestructors(); // in heap-checker.cc
-
-// A helper class to ensure that some components of heap leak checking
-// can happen before construction and after destruction
-// of all global/static objects.
-class HeapLeakCheckerGlobalPrePost {
- public:
- HeapLeakCheckerGlobalPrePost() {
- if (count_ == 0) {
- // The 'new int' will ensure that we have run an initial malloc
- // hook, which will set up the heap checker via
- // MallocHook_InitAtFirstAllocation_HeapLeakChecker. See malloc_hook.cc.
- // This is done in this roundabout fashion in order to avoid self-deadlock
- // if we directly called HeapLeakChecker_BeforeConstructors here.
- delete new int;
- // This needs to be called before the first allocation of an STL
- // object, but after libc is done setting up threads (because it
- // calls setenv, which requires a thread-aware errno). By
- // putting it here, we hope it's the first bit of code executed
- // after the libc global-constructor code.
- MallocExtension::Initialize();
- }
- ++count_;
- }
- ~HeapLeakCheckerGlobalPrePost() {
- if (count_ <= 0) abort();
- --count_;
- if (count_ == 0) HeapLeakChecker_AfterDestructors();
- }
- private:
- // Counter of constructions/destructions of objects of this class
- // (just in case there are more than one of them).
- static int count_;
-};
-
-int HeapLeakCheckerGlobalPrePost::count_ = 0;
-
-// The early-construction/late-destruction global object.
-static const HeapLeakCheckerGlobalPrePost heap_leak_checker_global_pre_post;
diff --git a/src/third_party/gperftools-2.5/src/heap-checker.cc b/src/third_party/gperftools-2.5/src/heap-checker.cc
deleted file mode 100755
index 9c82dea08e4..00000000000
--- a/src/third_party/gperftools-2.5/src/heap-checker.cc
+++ /dev/null
@@ -1,2388 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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.
-
-// ---
-// All Rights Reserved.
-//
-// Author: Maxim Lifantsev
-//
-
-#include "config.h"
-
-#include <fcntl.h> // for O_RDONLY (we use syscall to do actual reads)
-#include <string.h>
-#include <errno.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-#ifdef HAVE_PTHREAD
-#include <pthread.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <assert.h>
-
-#if defined(HAVE_LINUX_PTRACE_H)
-#include <linux/ptrace.h>
-#endif
-#ifdef HAVE_SYS_SYSCALL_H
-#include <sys/syscall.h>
-#endif
-#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__)
-#include <wtypes.h>
-#include <winbase.h>
-#undef ERROR // windows defines these as macros, which can cause trouble
-#undef max
-#undef min
-#endif
-
-#include <string>
-#include <vector>
-#include <map>
-#include <set>
-#include <algorithm>
-#include <functional>
-
-#include <gperftools/heap-checker.h>
-
-#include "base/basictypes.h"
-#include "base/googleinit.h"
-#include "base/logging.h"
-#include <gperftools/stacktrace.h>
-#include "base/commandlineflags.h"
-#include "base/elfcore.h" // for i386_regs
-#include "base/thread_lister.h"
-#include "heap-profile-table.h"
-#include "base/low_level_alloc.h"
-#include "malloc_hook-inl.h"
-#include <gperftools/malloc_hook.h>
-#include <gperftools/malloc_extension.h>
-#include "maybe_threads.h"
-#include "memory_region_map.h"
-#include "base/spinlock.h"
-#include "base/sysinfo.h"
-#include "base/stl_allocator.h"
-
-using std::string;
-using std::basic_string;
-using std::pair;
-using std::map;
-using std::set;
-using std::vector;
-using std::swap;
-using std::make_pair;
-using std::min;
-using std::max;
-using std::less;
-using std::char_traits;
-
-// If current process is being ptrace()d, 'TracerPid' in /proc/self/status
-// will be non-zero.
-static bool IsDebuggerAttached(void) { // only works under linux, probably
- char buf[256]; // TracerPid comes relatively earlier in status output
- int fd = open("/proc/self/status", O_RDONLY);
- if (fd == -1) {
- return false; // Can't tell for sure.
- }
- const int len = read(fd, buf, sizeof(buf));
- bool rc = false;
- if (len > 0) {
- const char *const kTracerPid = "TracerPid:\t";
- buf[len - 1] = '\0';
- const char *p = strstr(buf, kTracerPid);
- if (p != NULL) {
- rc = (strncmp(p + strlen(kTracerPid), "0\n", 2) != 0);
- }
- }
- close(fd);
- return rc;
-}
-
-// This is the default if you don't link in -lprofiler
-extern "C" {
-ATTRIBUTE_WEAK PERFTOOLS_DLL_DECL bool ProfilingIsEnabledForAllThreads();
-bool ProfilingIsEnabledForAllThreads() { return false; }
-}
-
-//----------------------------------------------------------------------
-// Flags that control heap-checking
-//----------------------------------------------------------------------
-
-DEFINE_string(heap_check,
- EnvToString("HEAPCHECK", ""),
- "The heap leak checking to be done over the whole executable: "
- "\"minimal\", \"normal\", \"strict\", "
- "\"draconian\", \"as-is\", and \"local\" "
- " or the empty string are the supported choices. "
- "(See HeapLeakChecker_InternalInitStart for details.)");
-
-DEFINE_bool(heap_check_report, true, "Obsolete");
-
-DEFINE_bool(heap_check_before_constructors,
- true,
- "deprecated; pretty much always true now");
-
-DEFINE_bool(heap_check_after_destructors,
- EnvToBool("HEAP_CHECK_AFTER_DESTRUCTORS", false),
- "If overall heap check is to end after global destructors "
- "or right after all REGISTER_HEAPCHECK_CLEANUP's");
-
-DEFINE_bool(heap_check_strict_check, true, "Obsolete");
-
-DEFINE_bool(heap_check_ignore_global_live,
- EnvToBool("HEAP_CHECK_IGNORE_GLOBAL_LIVE", true),
- "If overall heap check is to ignore heap objects reachable "
- "from the global data");
-
-DEFINE_bool(heap_check_identify_leaks,
- EnvToBool("HEAP_CHECK_IDENTIFY_LEAKS", false),
- "If heap check should generate the addresses of the leaked "
- "objects in the memory leak profiles. This may be useful "
- "in tracking down leaks where only a small fraction of "
- "objects allocated at the same stack trace are leaked.");
-
-DEFINE_bool(heap_check_ignore_thread_live,
- EnvToBool("HEAP_CHECK_IGNORE_THREAD_LIVE", true),
- "If set to true, objects reachable from thread stacks "
- "and registers are not reported as leaks");
-
-DEFINE_bool(heap_check_test_pointer_alignment,
- EnvToBool("HEAP_CHECK_TEST_POINTER_ALIGNMENT", false),
- "Set to true to check if the found leak can be due to "
- "use of unaligned pointers");
-
-// Alignment at which all pointers in memory are supposed to be located;
-// use 1 if any alignment is ok.
-// heap_check_test_pointer_alignment flag guides if we try the value of 1.
-// The larger it can be, the lesser is the chance of missing real leaks.
-static const size_t kPointerSourceAlignment = sizeof(void*);
-DEFINE_int32(heap_check_pointer_source_alignment,
- EnvToInt("HEAP_CHECK_POINTER_SOURCE_ALIGNMENT",
- kPointerSourceAlignment),
- "Alignment at which all pointers in memory are supposed to be "
- "located. Use 1 if any alignment is ok.");
-
-// A reasonable default to handle pointers inside of typical class objects:
-// Too low and we won't be able to traverse pointers to normally-used
-// nested objects and base parts of multiple-inherited objects.
-// Too high and it will both slow down leak checking (FindInsideAlloc
-// in HaveOnHeapLocked will get slower when there are large on-heap objects)
-// and make it probabilistically more likely to miss leaks
-// of large-sized objects.
-static const int64 kHeapCheckMaxPointerOffset = 1024;
-DEFINE_int64(heap_check_max_pointer_offset,
- EnvToInt("HEAP_CHECK_MAX_POINTER_OFFSET",
- kHeapCheckMaxPointerOffset),
- "Largest pointer offset for which we traverse "
- "pointers going inside of heap allocated objects. "
- "Set to -1 to use the actual largest heap object size.");
-
-DEFINE_bool(heap_check_run_under_gdb,
- EnvToBool("HEAP_CHECK_RUN_UNDER_GDB", false),
- "If false, turns off heap-checking library when running under gdb "
- "(normally, set to 'true' only when debugging the heap-checker)");
-
-DEFINE_int32(heap_check_delay_seconds, 0,
- "Number of seconds to delay on-exit heap checking."
- " If you set this flag,"
- " you may also want to set exit_timeout_seconds in order to"
- " avoid exit timeouts.\n"
- "NOTE: This flag is to be used only to help diagnose issues"
- " where it is suspected that the heap checker is reporting"
- " false leaks that will disappear if the heap checker delays"
- " its checks. Report any such issues to the heap-checker"
- " maintainer(s).");
-
-//----------------------------------------------------------------------
-
-DEFINE_string(heap_profile_pprof,
- EnvToString("PPROF_PATH", "pprof"),
- "OBSOLETE; not used");
-
-DEFINE_string(heap_check_dump_directory,
- EnvToString("HEAP_CHECK_DUMP_DIRECTORY", "/tmp"),
- "Directory to put heap-checker leak dump information");
-
-
-//----------------------------------------------------------------------
-// HeapLeakChecker global data
-//----------------------------------------------------------------------
-
-// Global lock for all the global data of this module.
-static SpinLock heap_checker_lock(SpinLock::LINKER_INITIALIZED);
-
-//----------------------------------------------------------------------
-
-// Heap profile prefix for leak checking profiles.
-// Gets assigned once when leak checking is turned on, then never modified.
-static const string* profile_name_prefix = NULL;
-
-// Whole-program heap leak checker.
-// Gets assigned once when leak checking is turned on,
-// then main_heap_checker is never deleted.
-static HeapLeakChecker* main_heap_checker = NULL;
-
-// Whether we will use main_heap_checker to do a check at program exit
-// automatically. In any case user can ask for more checks on main_heap_checker
-// via GlobalChecker().
-static bool do_main_heap_check = false;
-
-// The heap profile we use to collect info about the heap.
-// This is created in HeapLeakChecker::BeforeConstructorsLocked
-// together with setting heap_checker_on (below) to true
-// and registering our new/delete malloc hooks;
-// similarly all are unset in HeapLeakChecker::TurnItselfOffLocked.
-static HeapProfileTable* heap_profile = NULL;
-
-// If we are doing (or going to do) any kind of heap-checking.
-static bool heap_checker_on = false;
-
-// pid of the process that does whole-program heap leak checking
-static pid_t heap_checker_pid = 0;
-
-// If we did heap profiling during global constructors execution
-static bool constructor_heap_profiling = false;
-
-// RAW_VLOG level we dump key INFO messages at. If you want to turn
-// off these messages, set the environment variable PERFTOOLS_VERBOSE=-1.
-static const int heap_checker_info_level = 0;
-
-//----------------------------------------------------------------------
-// HeapLeakChecker's own memory allocator that is
-// independent of the normal program allocator.
-//----------------------------------------------------------------------
-
-// Wrapper of LowLevelAlloc for STL_Allocator and direct use.
-// We always access this class under held heap_checker_lock,
-// this allows us to in particular protect the period when threads are stopped
-// at random spots with TCMalloc_ListAllProcessThreads by heap_checker_lock,
-// w/o worrying about the lock in LowLevelAlloc::Arena.
-// We rely on the fact that we use an own arena with an own lock here.
-class HeapLeakChecker::Allocator {
- public:
- static void Init() {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- RAW_DCHECK(arena_ == NULL, "");
- arena_ = LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena());
- }
- static void Shutdown() {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- if (!LowLevelAlloc::DeleteArena(arena_) || alloc_count_ != 0) {
- RAW_LOG(FATAL, "Internal heap checker leak of %d objects", alloc_count_);
- }
- }
- static int alloc_count() {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- return alloc_count_;
- }
- static void* Allocate(size_t n) {
- RAW_DCHECK(arena_ && heap_checker_lock.IsHeld(), "");
- void* p = LowLevelAlloc::AllocWithArena(n, arena_);
- if (p) alloc_count_ += 1;
- return p;
- }
- static void Free(void* p) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- if (p) alloc_count_ -= 1;
- LowLevelAlloc::Free(p);
- }
- static void Free(void* p, size_t /* n */) {
- Free(p);
- }
- // destruct, free, and make *p to be NULL
- template<typename T> static void DeleteAndNull(T** p) {
- (*p)->~T();
- Free(*p);
- *p = NULL;
- }
- template<typename T> static void DeleteAndNullIfNot(T** p) {
- if (*p != NULL) DeleteAndNull(p);
- }
- private:
- static LowLevelAlloc::Arena* arena_;
- static int alloc_count_;
-};
-
-LowLevelAlloc::Arena* HeapLeakChecker::Allocator::arena_ = NULL;
-int HeapLeakChecker::Allocator::alloc_count_ = 0;
-
-//----------------------------------------------------------------------
-// HeapLeakChecker live object tracking components
-//----------------------------------------------------------------------
-
-// Cases of live object placement we distinguish
-enum ObjectPlacement {
- MUST_BE_ON_HEAP, // Must point to a live object of the matching size in the
- // heap_profile map of the heap when we get to it
- IGNORED_ON_HEAP, // Is a live (ignored) object on heap
- MAYBE_LIVE, // Is a piece of writable memory from /proc/self/maps
- IN_GLOBAL_DATA, // Is part of global data region of the executable
- THREAD_DATA, // Part of a thread stack and a thread descriptor with TLS
- THREAD_REGISTERS, // Values in registers of some thread
-};
-
-// Information about an allocated object
-struct AllocObject {
- const void* ptr; // the object
- uintptr_t size; // its size
- ObjectPlacement place; // where ptr points to
-
- AllocObject(const void* p, size_t s, ObjectPlacement l)
- : ptr(p), size(s), place(l) { }
-};
-
-// All objects (memory ranges) ignored via HeapLeakChecker::IgnoreObject
-// Key is the object's address; value is its size.
-typedef map<uintptr_t, size_t, less<uintptr_t>,
- STL_Allocator<pair<const uintptr_t, size_t>,
- HeapLeakChecker::Allocator>
- > IgnoredObjectsMap;
-static IgnoredObjectsMap* ignored_objects = NULL;
-
-// All objects (memory ranges) that we consider to be the sources of pointers
-// to live (not leaked) objects.
-// At different times this holds (what can be reached from) global data regions
-// and the objects we've been told to ignore.
-// For any AllocObject::ptr "live_objects" is supposed to contain at most one
-// record at any time. We maintain this by checking with the heap_profile map
-// of the heap and removing the live heap objects we've handled from it.
-// This vector is maintained as a stack and the frontier of reachable
-// live heap objects in our flood traversal of them.
-typedef vector<AllocObject,
- STL_Allocator<AllocObject, HeapLeakChecker::Allocator>
- > LiveObjectsStack;
-static LiveObjectsStack* live_objects = NULL;
-
-// A special string type that uses my allocator
-typedef basic_string<char, char_traits<char>,
- STL_Allocator<char, HeapLeakChecker::Allocator>
- > HCL_string;
-
-// A placeholder to fill-in the starting values for live_objects
-// for each library so we can keep the library-name association for logging.
-typedef map<HCL_string, LiveObjectsStack, less<HCL_string>,
- STL_Allocator<pair<const HCL_string, LiveObjectsStack>,
- HeapLeakChecker::Allocator>
- > LibraryLiveObjectsStacks;
-static LibraryLiveObjectsStacks* library_live_objects = NULL;
-
-// Value stored in the map of disabled address ranges;
-// its key is the end of the address range.
-// We'll ignore allocations with a return address in a disabled range
-// if the address occurs at 'max_depth' or less in the stack trace.
-struct HeapLeakChecker::RangeValue {
- uintptr_t start_address; // the start of the range
- int max_depth; // the maximal stack depth to disable at
-};
-typedef map<uintptr_t, HeapLeakChecker::RangeValue, less<uintptr_t>,
- STL_Allocator<pair<const uintptr_t, HeapLeakChecker::RangeValue>,
- HeapLeakChecker::Allocator>
- > DisabledRangeMap;
-// The disabled program counter address ranges for profile dumping
-// that are registered with HeapLeakChecker::DisableChecksFromToLocked.
-static DisabledRangeMap* disabled_ranges = NULL;
-
-// Set of stack tops.
-// These are used to consider live only appropriate chunks of the memory areas
-// that are used for stacks (and maybe thread-specific data as well)
-// so that we do not treat pointers from outdated stack frames as live.
-typedef set<uintptr_t, less<uintptr_t>,
- STL_Allocator<uintptr_t, HeapLeakChecker::Allocator>
- > StackTopSet;
-static StackTopSet* stack_tops = NULL;
-
-// A map of ranges of code addresses for the system libraries
-// that can mmap/mremap/sbrk-allocate memory regions for stacks
-// and thread-local storage that we want to consider as live global data.
-// Maps from the end address to the start address.
-typedef map<uintptr_t, uintptr_t, less<uintptr_t>,
- STL_Allocator<pair<const uintptr_t, uintptr_t>,
- HeapLeakChecker::Allocator>
- > GlobalRegionCallerRangeMap;
-static GlobalRegionCallerRangeMap* global_region_caller_ranges = NULL;
-
-// TODO(maxim): make our big data structs into own modules
-
-// Disabler is implemented by keeping track of a per-thread count
-// of active Disabler objects. Any objects allocated while the
-// count > 0 are not reported.
-
-#ifdef HAVE_TLS
-
-static __thread int thread_disable_counter
-// The "inital exec" model is faster than the default TLS model, at
-// the cost you can't dlopen this library. But dlopen on heap-checker
-// doesn't work anyway -- it must run before main -- so this is a good
-// trade-off.
-# ifdef HAVE___ATTRIBUTE__
- __attribute__ ((tls_model ("initial-exec")))
-# endif
- ;
-inline int get_thread_disable_counter() {
- return thread_disable_counter;
-}
-inline void set_thread_disable_counter(int value) {
- thread_disable_counter = value;
-}
-
-#else // #ifdef HAVE_TLS
-
-static pthread_key_t thread_disable_counter_key;
-static int main_thread_counter; // storage for use before main()
-static bool use_main_thread_counter = true;
-
-// TODO(csilvers): this is called from NewHook, in the middle of malloc().
-// If perftools_pthread_getspecific calls malloc, that will lead to an
-// infinite loop. I don't know how to fix that, so I hope it never happens!
-inline int get_thread_disable_counter() {
- if (use_main_thread_counter) // means we're running really early
- return main_thread_counter;
- void* p = perftools_pthread_getspecific(thread_disable_counter_key);
- return (intptr_t)p; // kinda evil: store the counter directly in the void*
-}
-
-inline void set_thread_disable_counter(int value) {
- if (use_main_thread_counter) { // means we're running really early
- main_thread_counter = value;
- return;
- }
- intptr_t pointer_sized_value = value;
- // kinda evil: store the counter directly in the void*
- void* p = (void*)pointer_sized_value;
- // NOTE: this may call malloc, which will call NewHook which will call
- // get_thread_disable_counter() which will call pthread_getspecific(). I
- // don't know if anything bad can happen if we call getspecific() in the
- // middle of a setspecific() call. It seems to work ok in practice...
- perftools_pthread_setspecific(thread_disable_counter_key, p);
-}
-
-// The idea here is that this initializer will run pretty late: after
-// pthreads have been totally set up. At this point we can call
-// pthreads routines, so we set those up.
-class InitThreadDisableCounter {
- public:
- InitThreadDisableCounter() {
- perftools_pthread_key_create(&thread_disable_counter_key, NULL);
- // Set up the main thread's value, which we have a special variable for.
- void* p = (void*)main_thread_counter; // store the counter directly
- perftools_pthread_setspecific(thread_disable_counter_key, p);
- use_main_thread_counter = false;
- }
-};
-InitThreadDisableCounter init_thread_disable_counter;
-
-#endif // #ifdef HAVE_TLS
-
-HeapLeakChecker::Disabler::Disabler() {
- // It is faster to unconditionally increment the thread-local
- // counter than to check whether or not heap-checking is on
- // in a thread-safe manner.
- int counter = get_thread_disable_counter();
- set_thread_disable_counter(counter + 1);
- RAW_VLOG(10, "Increasing thread disable counter to %d", counter + 1);
-}
-
-HeapLeakChecker::Disabler::~Disabler() {
- int counter = get_thread_disable_counter();
- RAW_DCHECK(counter > 0, "");
- if (counter > 0) {
- set_thread_disable_counter(counter - 1);
- RAW_VLOG(10, "Decreasing thread disable counter to %d", counter);
- } else {
- RAW_VLOG(0, "Thread disable counter underflow : %d", counter);
- }
-}
-
-//----------------------------------------------------------------------
-
-// The size of the largest heap object allocated so far.
-static size_t max_heap_object_size = 0;
-// The possible range of addresses that can point
-// into one of the elements of heap_objects.
-static uintptr_t min_heap_address = uintptr_t(-1LL);
-static uintptr_t max_heap_address = 0;
-
-//----------------------------------------------------------------------
-
-// Simple casting helpers for uintptr_t and void*:
-template<typename T>
-inline static const void* AsPtr(T addr) {
- return reinterpret_cast<void*>(addr);
-}
-inline static uintptr_t AsInt(const void* ptr) {
- return reinterpret_cast<uintptr_t>(ptr);
-}
-
-//----------------------------------------------------------------------
-
-// We've seen reports that strstr causes heap-checker crashes in some
-// libc's (?):
-// http://code.google.com/p/gperftools/issues/detail?id=263
-// It's simple enough to use our own. This is not in time-critical code.
-static const char* hc_strstr(const char* s1, const char* s2) {
- const size_t len = strlen(s2);
- RAW_CHECK(len > 0, "Unexpected empty string passed to strstr()");
- for (const char* p = strchr(s1, *s2); p != NULL; p = strchr(p+1, *s2)) {
- if (strncmp(p, s2, len) == 0) {
- return p;
- }
- }
- return NULL;
-}
-
-//----------------------------------------------------------------------
-
-// Our hooks for MallocHook
-static void NewHook(const void* ptr, size_t size) {
- if (ptr != NULL) {
- const int counter = get_thread_disable_counter();
- const bool ignore = (counter > 0);
- RAW_VLOG(16, "Recording Alloc: %p of %" PRIuS "; %d", ptr, size,
- int(counter));
-
- // Fetch the caller's stack trace before acquiring heap_checker_lock.
- void* stack[HeapProfileTable::kMaxStackDepth];
- int depth = HeapProfileTable::GetCallerStackTrace(0, stack);
-
- { SpinLockHolder l(&heap_checker_lock);
- if (size > max_heap_object_size) max_heap_object_size = size;
- uintptr_t addr = AsInt(ptr);
- if (addr < min_heap_address) min_heap_address = addr;
- addr += size;
- if (addr > max_heap_address) max_heap_address = addr;
- if (heap_checker_on) {
- heap_profile->RecordAlloc(ptr, size, depth, stack);
- if (ignore) {
- heap_profile->MarkAsIgnored(ptr);
- }
- }
- }
- RAW_VLOG(17, "Alloc Recorded: %p of %" PRIuS "", ptr, size);
- }
-}
-
-static void DeleteHook(const void* ptr) {
- if (ptr != NULL) {
- RAW_VLOG(16, "Recording Free %p", ptr);
- { SpinLockHolder l(&heap_checker_lock);
- if (heap_checker_on) heap_profile->RecordFree(ptr);
- }
- RAW_VLOG(17, "Free Recorded: %p", ptr);
- }
-}
-
-//----------------------------------------------------------------------
-
-enum StackDirection {
- GROWS_TOWARDS_HIGH_ADDRESSES,
- GROWS_TOWARDS_LOW_ADDRESSES,
- UNKNOWN_DIRECTION
-};
-
-// Determine which way the stack grows:
-
-static StackDirection ATTRIBUTE_NOINLINE GetStackDirection(
- const uintptr_t *const ptr) {
- uintptr_t x;
- if (&x < ptr)
- return GROWS_TOWARDS_LOW_ADDRESSES;
- if (ptr < &x)
- return GROWS_TOWARDS_HIGH_ADDRESSES;
-
- RAW_CHECK(0, ""); // Couldn't determine the stack direction.
-
- return UNKNOWN_DIRECTION;
-}
-
-// Direction of stack growth (will initialize via GetStackDirection())
-static StackDirection stack_direction = UNKNOWN_DIRECTION;
-
-// This routine is called for every thread stack we know about to register it.
-static void RegisterStackLocked(const void* top_ptr) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- RAW_DCHECK(MemoryRegionMap::LockIsHeld(), "");
- RAW_VLOG(10, "Thread stack at %p", top_ptr);
- uintptr_t top = AsInt(top_ptr);
- stack_tops->insert(top); // add for later use
-
- // make sure stack_direction is initialized
- if (stack_direction == UNKNOWN_DIRECTION) {
- stack_direction = GetStackDirection(&top);
- }
-
- // Find memory region with this stack
- MemoryRegionMap::Region region;
- if (MemoryRegionMap::FindAndMarkStackRegion(top, &region)) {
- // Make the proper portion of the stack live:
- if (stack_direction == GROWS_TOWARDS_LOW_ADDRESSES) {
- RAW_VLOG(11, "Live stack at %p of %" PRIuPTR " bytes",
- top_ptr, region.end_addr - top);
- live_objects->push_back(AllocObject(top_ptr, region.end_addr - top,
- THREAD_DATA));
- } else { // GROWS_TOWARDS_HIGH_ADDRESSES
- RAW_VLOG(11, "Live stack at %p of %" PRIuPTR " bytes",
- AsPtr(region.start_addr),
- top - region.start_addr);
- live_objects->push_back(AllocObject(AsPtr(region.start_addr),
- top - region.start_addr,
- THREAD_DATA));
- }
- // not in MemoryRegionMap, look in library_live_objects:
- } else if (FLAGS_heap_check_ignore_global_live) {
- for (LibraryLiveObjectsStacks::iterator lib = library_live_objects->begin();
- lib != library_live_objects->end(); ++lib) {
- for (LiveObjectsStack::iterator span = lib->second.begin();
- span != lib->second.end(); ++span) {
- uintptr_t start = AsInt(span->ptr);
- uintptr_t end = start + span->size;
- if (start <= top && top < end) {
- RAW_VLOG(11, "Stack at %p is inside /proc/self/maps chunk %p..%p",
- top_ptr, AsPtr(start), AsPtr(end));
- // Shrink start..end region by chopping away the memory regions in
- // MemoryRegionMap that land in it to undo merging of regions
- // in /proc/self/maps, so that we correctly identify what portion
- // of start..end is actually the stack region.
- uintptr_t stack_start = start;
- uintptr_t stack_end = end;
- // can optimize-away this loop, but it does not run often
- RAW_DCHECK(MemoryRegionMap::LockIsHeld(), "");
- for (MemoryRegionMap::RegionIterator r =
- MemoryRegionMap::BeginRegionLocked();
- r != MemoryRegionMap::EndRegionLocked(); ++r) {
- if (top < r->start_addr && r->start_addr < stack_end) {
- stack_end = r->start_addr;
- }
- if (stack_start < r->end_addr && r->end_addr <= top) {
- stack_start = r->end_addr;
- }
- }
- if (stack_start != start || stack_end != end) {
- RAW_VLOG(11, "Stack at %p is actually inside memory chunk %p..%p",
- top_ptr, AsPtr(stack_start), AsPtr(stack_end));
- }
- // Make the proper portion of the stack live:
- if (stack_direction == GROWS_TOWARDS_LOW_ADDRESSES) {
- RAW_VLOG(11, "Live stack at %p of %" PRIuPTR " bytes",
- top_ptr, stack_end - top);
- live_objects->push_back(
- AllocObject(top_ptr, stack_end - top, THREAD_DATA));
- } else { // GROWS_TOWARDS_HIGH_ADDRESSES
- RAW_VLOG(11, "Live stack at %p of %" PRIuPTR " bytes",
- AsPtr(stack_start), top - stack_start);
- live_objects->push_back(
- AllocObject(AsPtr(stack_start), top - stack_start, THREAD_DATA));
- }
- lib->second.erase(span); // kill the rest of the region
- // Put the non-stack part(s) of the region back:
- if (stack_start != start) {
- lib->second.push_back(AllocObject(AsPtr(start), stack_start - start,
- MAYBE_LIVE));
- }
- if (stack_end != end) {
- lib->second.push_back(AllocObject(AsPtr(stack_end), end - stack_end,
- MAYBE_LIVE));
- }
- return;
- }
- }
- }
- RAW_LOG(ERROR, "Memory region for stack at %p not found. "
- "Will likely report false leak positives.", top_ptr);
- }
-}
-
-// Iterator for heap allocation map data to make ignored objects "live"
-// (i.e., treated as roots for the mark-and-sweep phase)
-static void MakeIgnoredObjectsLiveCallbackLocked(
- const void* ptr, const HeapProfileTable::AllocInfo& info) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- if (info.ignored) {
- live_objects->push_back(AllocObject(ptr, info.object_size,
- MUST_BE_ON_HEAP));
- }
-}
-
-// Iterator for heap allocation map data to make objects allocated from
-// disabled regions of code to be live.
-static void MakeDisabledLiveCallbackLocked(
- const void* ptr, const HeapProfileTable::AllocInfo& info) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- bool stack_disable = false;
- bool range_disable = false;
- for (int depth = 0; depth < info.stack_depth; depth++) {
- uintptr_t addr = AsInt(info.call_stack[depth]);
- if (disabled_ranges) {
- DisabledRangeMap::const_iterator iter
- = disabled_ranges->upper_bound(addr);
- if (iter != disabled_ranges->end()) {
- RAW_DCHECK(iter->first > addr, "");
- if (iter->second.start_address < addr &&
- iter->second.max_depth > depth) {
- range_disable = true; // in range; dropping
- break;
- }
- }
- }
- }
- if (stack_disable || range_disable) {
- uintptr_t start_address = AsInt(ptr);
- uintptr_t end_address = start_address + info.object_size;
- StackTopSet::const_iterator iter
- = stack_tops->lower_bound(start_address);
- if (iter != stack_tops->end()) {
- RAW_DCHECK(*iter >= start_address, "");
- if (*iter < end_address) {
- // We do not disable (treat as live) whole allocated regions
- // if they are used to hold thread call stacks
- // (i.e. when we find a stack inside).
- // The reason is that we'll treat as live the currently used
- // stack portions anyway (see RegisterStackLocked),
- // and the rest of the region where the stack lives can well
- // contain outdated stack variables which are not live anymore,
- // hence should not be treated as such.
- RAW_VLOG(11, "Not %s-disabling %" PRIuS " bytes at %p"
- ": have stack inside: %p",
- (stack_disable ? "stack" : "range"),
- info.object_size, ptr, AsPtr(*iter));
- return;
- }
- }
- RAW_VLOG(11, "%s-disabling %" PRIuS " bytes at %p",
- (stack_disable ? "Stack" : "Range"), info.object_size, ptr);
- live_objects->push_back(AllocObject(ptr, info.object_size,
- MUST_BE_ON_HEAP));
- }
-}
-
-static const char kUnnamedProcSelfMapEntry[] = "UNNAMED";
-
-// This function takes some fields from a /proc/self/maps line:
-//
-// start_address start address of a memory region.
-// end_address end address of a memory region
-// permissions rwx + private/shared bit
-// filename filename of the mapped file
-//
-// If the region is not writeable, then it cannot have any heap
-// pointers in it, otherwise we record it as a candidate live region
-// to get filtered later.
-static void RecordGlobalDataLocked(uintptr_t start_address,
- uintptr_t end_address,
- const char* permissions,
- const char* filename) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- // Ignore non-writeable regions.
- if (strchr(permissions, 'w') == NULL) return;
- if (filename == NULL || *filename == '\0') {
- filename = kUnnamedProcSelfMapEntry;
- }
- RAW_VLOG(11, "Looking into %s: 0x%" PRIxPTR "..0x%" PRIxPTR,
- filename, start_address, end_address);
- (*library_live_objects)[filename].
- push_back(AllocObject(AsPtr(start_address),
- end_address - start_address,
- MAYBE_LIVE));
-}
-
-// See if 'library' from /proc/self/maps has base name 'library_base'
-// i.e. contains it and has '.' or '-' after it.
-static bool IsLibraryNamed(const char* library, const char* library_base) {
- const char* p = hc_strstr(library, library_base);
- size_t sz = strlen(library_base);
- return p != NULL && (p[sz] == '.' || p[sz] == '-');
-}
-
-// static
-void HeapLeakChecker::DisableLibraryAllocsLocked(const char* library,
- uintptr_t start_address,
- uintptr_t end_address) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- int depth = 0;
- // TODO(maxim): maybe this should be extended to also use objdump
- // and pick the text portion of the library more precisely.
- if (IsLibraryNamed(library, "/libpthread") ||
- // libpthread has a lot of small "system" leaks we don't care about.
- // In particular it allocates memory to store data supplied via
- // pthread_setspecific (which can be the only pointer to a heap object).
- IsLibraryNamed(library, "/libdl") ||
- // library loaders leak some "system" heap that we don't care about
- IsLibraryNamed(library, "/libcrypto") ||
- // Sometimes libcrypto of OpenSSH is compiled with -fomit-frame-pointer
- // (any library can be, of course, but this one often is because speed
- // is so important for making crypto usable). We ignore all its
- // allocations because we can't see the call stacks. We'd prefer
- // to ignore allocations done in files/symbols that match
- // "default_malloc_ex|default_realloc_ex"
- // but that doesn't work when the end-result binary is stripped.
- IsLibraryNamed(library, "/libjvm") ||
- // JVM has a lot of leaks we don't care about.
- IsLibraryNamed(library, "/libzip")
- // The JVM leaks java.util.zip.Inflater after loading classes.
- ) {
- depth = 1; // only disable allocation calls directly from the library code
- } else if (IsLibraryNamed(library, "/ld")
- // library loader leaks some "system" heap
- // (e.g. thread-local storage) that we don't care about
- ) {
- depth = 2; // disable allocation calls directly from the library code
- // and at depth 2 from it.
- // We need depth 2 here solely because of a libc bug that
- // forces us to jump through __memalign_hook and MemalignOverride hoops
- // in tcmalloc.cc.
- // Those buggy __libc_memalign() calls are in ld-linux.so and happen for
- // thread-local storage allocations that we want to ignore here.
- // We go with the depth-2 hack as a workaround for this libc bug:
- // otherwise we'd need to extend MallocHook interface
- // so that correct stack depth adjustment can be propagated from
- // the exceptional case of MemalignOverride.
- // Using depth 2 here should not mask real leaks because ld-linux.so
- // does not call user code.
- }
- if (depth) {
- RAW_VLOG(10, "Disabling allocations from %s at depth %d:", library, depth);
- DisableChecksFromToLocked(AsPtr(start_address), AsPtr(end_address), depth);
- if (IsLibraryNamed(library, "/libpthread") ||
- IsLibraryNamed(library, "/libdl") ||
- IsLibraryNamed(library, "/ld")) {
- RAW_VLOG(10, "Global memory regions made by %s will be live data",
- library);
- if (global_region_caller_ranges == NULL) {
- global_region_caller_ranges =
- new(Allocator::Allocate(sizeof(GlobalRegionCallerRangeMap)))
- GlobalRegionCallerRangeMap;
- }
- global_region_caller_ranges
- ->insert(make_pair(end_address, start_address));
- }
- }
-}
-
-// static
-HeapLeakChecker::ProcMapsResult HeapLeakChecker::UseProcMapsLocked(
- ProcMapsTask proc_maps_task) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- // Need to provide own scratch memory to ProcMapsIterator:
- ProcMapsIterator::Buffer buffer;
- ProcMapsIterator it(0, &buffer);
- if (!it.Valid()) {
- int errsv = errno;
- RAW_LOG(ERROR, "Could not open /proc/self/maps: errno=%d. "
- "Libraries will not be handled correctly.", errsv);
- return CANT_OPEN_PROC_MAPS;
- }
- uint64 start_address, end_address, file_offset;
- int64 inode;
- char *permissions, *filename;
- bool saw_shared_lib = false;
- bool saw_nonzero_inode = false;
- bool saw_shared_lib_with_nonzero_inode = false;
- while (it.Next(&start_address, &end_address, &permissions,
- &file_offset, &inode, &filename)) {
- if (start_address >= end_address) {
- // Warn if a line we can be interested in is ill-formed:
- if (inode != 0) {
- RAW_LOG(ERROR, "Errors reading /proc/self/maps. "
- "Some global memory regions will not "
- "be handled correctly.");
- }
- // Silently skip other ill-formed lines: some are possible
- // probably due to the interplay of how /proc/self/maps is updated
- // while we read it in chunks in ProcMapsIterator and
- // do things in this loop.
- continue;
- }
- // Determine if any shared libraries are present (this is the same
- // list of extensions as is found in pprof). We want to ignore
- // 'fake' libraries with inode 0 when determining. However, some
- // systems don't share inodes via /proc, so we turn off this check
- // if we don't see any evidence that we're getting inode info.
- if (inode != 0) {
- saw_nonzero_inode = true;
- }
- if ((hc_strstr(filename, "lib") && hc_strstr(filename, ".so")) ||
- hc_strstr(filename, ".dll") ||
- // not all .dylib filenames start with lib. .dylib is big enough
- // that we are unlikely to get false matches just checking that.
- hc_strstr(filename, ".dylib") || hc_strstr(filename, ".bundle")) {
- saw_shared_lib = true;
- if (inode != 0) {
- saw_shared_lib_with_nonzero_inode = true;
- }
- }
-
- switch (proc_maps_task) {
- case DISABLE_LIBRARY_ALLOCS:
- // All lines starting like
- // "401dc000-4030f000 r??p 00132000 03:01 13991972 lib/bin"
- // identify a data and code sections of a shared library or our binary
- if (inode != 0 && strncmp(permissions, "r-xp", 4) == 0) {
- DisableLibraryAllocsLocked(filename, start_address, end_address);
- }
- break;
- case RECORD_GLOBAL_DATA:
- RecordGlobalDataLocked(start_address, end_address,
- permissions, filename);
- break;
- default:
- RAW_CHECK(0, "");
- }
- }
- // If /proc/self/maps is reporting inodes properly (we saw a
- // non-zero inode), then we only say we saw a shared lib if we saw a
- // 'real' one, with a non-zero inode.
- if (saw_nonzero_inode) {
- saw_shared_lib = saw_shared_lib_with_nonzero_inode;
- }
- if (!saw_shared_lib) {
- RAW_LOG(ERROR, "No shared libs detected. Will likely report false leak "
- "positives for statically linked executables.");
- return NO_SHARED_LIBS_IN_PROC_MAPS;
- }
- return PROC_MAPS_USED;
-}
-
-// Total number and size of live objects dropped from the profile;
-// (re)initialized in IgnoreAllLiveObjectsLocked.
-static int64 live_objects_total;
-static int64 live_bytes_total;
-
-// pid of the thread that is doing the current leak check
-// (protected by our lock; IgnoreAllLiveObjectsLocked sets it)
-static pid_t self_thread_pid = 0;
-
-// Status of our thread listing callback execution
-// (protected by our lock; used from within IgnoreAllLiveObjectsLocked)
-static enum {
- CALLBACK_NOT_STARTED,
- CALLBACK_STARTED,
- CALLBACK_COMPLETED,
-} thread_listing_status = CALLBACK_NOT_STARTED;
-
-// Ideally to avoid deadlocks this function should not result in any libc
-// or other function calls that might need to lock a mutex:
-// It is called when all threads of a process are stopped
-// at arbitrary points thus potentially holding those locks.
-//
-// In practice we are calling some simple i/o and sprintf-type library functions
-// for logging messages, but use only our own LowLevelAlloc::Arena allocator.
-//
-// This is known to be buggy: the library i/o function calls are able to cause
-// deadlocks when they request a lock that a stopped thread happens to hold.
-// This issue as far as we know have so far not resulted in any deadlocks
-// in practice, so for now we are taking our chance that the deadlocks
-// have insignificant frequency.
-//
-// If such deadlocks become a problem we should make the i/o calls
-// into appropriately direct system calls (or eliminate them),
-// in particular write() is not safe and vsnprintf() is potentially dangerous
-// due to reliance on locale functions (these are called through RAW_LOG
-// and in other ways).
-//
-
-#if defined(HAVE_LINUX_PTRACE_H) && defined(HAVE_SYS_SYSCALL_H) && defined(DUMPER)
-# if (defined(__i386__) || defined(__x86_64))
-# define THREAD_REGS i386_regs
-# elif defined(__PPC__)
-# define THREAD_REGS ppc_regs
-# endif
-#endif
-
-/*static*/ int HeapLeakChecker::IgnoreLiveThreadsLocked(void* parameter,
- int num_threads,
- pid_t* thread_pids,
- va_list /*ap*/) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- thread_listing_status = CALLBACK_STARTED;
- RAW_VLOG(11, "Found %d threads (from pid %d)", num_threads, getpid());
-
- if (FLAGS_heap_check_ignore_global_live) {
- UseProcMapsLocked(RECORD_GLOBAL_DATA);
- }
-
- // We put the registers from other threads here
- // to make pointers stored in them live.
- vector<void*, STL_Allocator<void*, Allocator> > thread_registers;
-
- int failures = 0;
- for (int i = 0; i < num_threads; ++i) {
- // the leak checking thread itself is handled
- // specially via self_thread_stack, not here:
- if (thread_pids[i] == self_thread_pid) continue;
- RAW_VLOG(11, "Handling thread with pid %d", thread_pids[i]);
-#ifdef THREAD_REGS
- THREAD_REGS thread_regs;
-#define sys_ptrace(r, p, a, d) syscall(SYS_ptrace, (r), (p), (a), (d))
- // We use sys_ptrace to avoid thread locking
- // because this is called from TCMalloc_ListAllProcessThreads
- // when all but this thread are suspended.
- if (sys_ptrace(PTRACE_GETREGS, thread_pids[i], NULL, &thread_regs) == 0) {
- // Need to use SP to get all the data from the very last stack frame:
- COMPILE_ASSERT(sizeof(thread_regs.SP) == sizeof(void*),
- SP_register_does_not_look_like_a_pointer);
- RegisterStackLocked(reinterpret_cast<void*>(thread_regs.SP));
- // Make registers live (just in case PTRACE_ATTACH resulted in some
- // register pointers still being in the registers and not on the stack):
- for (void** p = reinterpret_cast<void**>(&thread_regs);
- p < reinterpret_cast<void**>(&thread_regs + 1); ++p) {
- RAW_VLOG(12, "Thread register %p", *p);
- thread_registers.push_back(*p);
- }
- } else {
- failures += 1;
- }
-#else
- failures += 1;
-#endif
- }
- // Use all the collected thread (stack) liveness sources:
- IgnoreLiveObjectsLocked("threads stack data", "");
- if (thread_registers.size()) {
- // Make thread registers be live heap data sources.
- // we rely here on the fact that vector is in one memory chunk:
- RAW_VLOG(11, "Live registers at %p of %" PRIuS " bytes",
- &thread_registers[0], thread_registers.size() * sizeof(void*));
- live_objects->push_back(AllocObject(&thread_registers[0],
- thread_registers.size() * sizeof(void*),
- THREAD_REGISTERS));
- IgnoreLiveObjectsLocked("threads register data", "");
- }
- // Do all other liveness walking while all threads are stopped:
- IgnoreNonThreadLiveObjectsLocked();
- // Can now resume the threads:
- TCMalloc_ResumeAllProcessThreads(num_threads, thread_pids);
- thread_listing_status = CALLBACK_COMPLETED;
- return failures;
-}
-
-// Stack top of the thread that is doing the current leak check
-// (protected by our lock; IgnoreAllLiveObjectsLocked sets it)
-static const void* self_thread_stack_top;
-
-// static
-void HeapLeakChecker::IgnoreNonThreadLiveObjectsLocked() {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- RAW_DCHECK(MemoryRegionMap::LockIsHeld(), "");
- RAW_VLOG(11, "Handling self thread with pid %d", self_thread_pid);
- // Register our own stack:
-
- // Important that all stack ranges (including the one here)
- // are known before we start looking at them
- // in MakeDisabledLiveCallbackLocked:
- RegisterStackLocked(self_thread_stack_top);
- IgnoreLiveObjectsLocked("stack data", "");
-
- // Make objects we were told to ignore live:
- if (ignored_objects) {
- for (IgnoredObjectsMap::const_iterator object = ignored_objects->begin();
- object != ignored_objects->end(); ++object) {
- const void* ptr = AsPtr(object->first);
- RAW_VLOG(11, "Ignored live object at %p of %" PRIuS " bytes",
- ptr, object->second);
- live_objects->
- push_back(AllocObject(ptr, object->second, MUST_BE_ON_HEAP));
- // we do this liveness check for ignored_objects before doing any
- // live heap walking to make sure it does not fail needlessly:
- size_t object_size;
- if (!(heap_profile->FindAlloc(ptr, &object_size) &&
- object->second == object_size)) {
- RAW_LOG(FATAL, "Object at %p of %" PRIuS " bytes from an"
- " IgnoreObject() has disappeared", ptr, object->second);
- }
- }
- IgnoreLiveObjectsLocked("ignored objects", "");
- }
-
- // Treat objects that were allocated when a Disabler was live as
- // roots. I.e., if X was allocated while a Disabler was active,
- // and Y is reachable from X, arrange that neither X nor Y are
- // treated as leaks.
- heap_profile->IterateAllocs(MakeIgnoredObjectsLiveCallbackLocked);
- IgnoreLiveObjectsLocked("disabled objects", "");
-
- // Make code-address-disabled objects live and ignored:
- // This in particular makes all thread-specific data live
- // because the basic data structure to hold pointers to thread-specific data
- // is allocated from libpthreads and we have range-disabled that
- // library code with UseProcMapsLocked(DISABLE_LIBRARY_ALLOCS);
- // so now we declare all thread-specific data reachable from there as live.
- heap_profile->IterateAllocs(MakeDisabledLiveCallbackLocked);
- IgnoreLiveObjectsLocked("disabled code", "");
-
- // Actually make global data live:
- if (FLAGS_heap_check_ignore_global_live) {
- bool have_null_region_callers = false;
- for (LibraryLiveObjectsStacks::iterator l = library_live_objects->begin();
- l != library_live_objects->end(); ++l) {
- RAW_CHECK(live_objects->empty(), "");
- // Process library_live_objects in l->second
- // filtering them by MemoryRegionMap:
- // It's safe to iterate over MemoryRegionMap
- // w/o locks here as we are inside MemoryRegionMap::Lock():
- RAW_DCHECK(MemoryRegionMap::LockIsHeld(), "");
- // The only change to MemoryRegionMap possible in this loop
- // is region addition as a result of allocating more memory
- // for live_objects. This won't invalidate the RegionIterator
- // or the intent of the loop.
- // --see the comment by MemoryRegionMap::BeginRegionLocked().
- for (MemoryRegionMap::RegionIterator region =
- MemoryRegionMap::BeginRegionLocked();
- region != MemoryRegionMap::EndRegionLocked(); ++region) {
- // "region" from MemoryRegionMap is to be subtracted from
- // (tentatively live) regions in l->second
- // if it has a stack inside or it was allocated by
- // a non-special caller (not one covered by a range
- // in global_region_caller_ranges).
- // This will in particular exclude all memory chunks used
- // by the heap itself as well as what's been allocated with
- // any allocator on top of mmap.
- bool subtract = true;
- if (!region->is_stack && global_region_caller_ranges) {
- if (region->caller() == static_cast<uintptr_t>(NULL)) {
- have_null_region_callers = true;
- } else {
- GlobalRegionCallerRangeMap::const_iterator iter
- = global_region_caller_ranges->upper_bound(region->caller());
- if (iter != global_region_caller_ranges->end()) {
- RAW_DCHECK(iter->first > region->caller(), "");
- if (iter->second < region->caller()) { // in special region
- subtract = false;
- }
- }
- }
- }
- if (subtract) {
- // The loop puts the result of filtering l->second into live_objects:
- for (LiveObjectsStack::const_iterator i = l->second.begin();
- i != l->second.end(); ++i) {
- // subtract *region from *i
- uintptr_t start = AsInt(i->ptr);
- uintptr_t end = start + i->size;
- if (region->start_addr <= start && end <= region->end_addr) {
- // full deletion due to subsumption
- } else if (start < region->start_addr &&
- region->end_addr < end) { // cutting-out split
- live_objects->push_back(AllocObject(i->ptr,
- region->start_addr - start,
- IN_GLOBAL_DATA));
- live_objects->push_back(AllocObject(AsPtr(region->end_addr),
- end - region->end_addr,
- IN_GLOBAL_DATA));
- } else if (region->end_addr > start &&
- region->start_addr <= start) { // cut from start
- live_objects->push_back(AllocObject(AsPtr(region->end_addr),
- end - region->end_addr,
- IN_GLOBAL_DATA));
- } else if (region->start_addr > start &&
- region->start_addr < end) { // cut from end
- live_objects->push_back(AllocObject(i->ptr,
- region->start_addr - start,
- IN_GLOBAL_DATA));
- } else { // pass: no intersection
- live_objects->push_back(AllocObject(i->ptr, i->size,
- IN_GLOBAL_DATA));
- }
- }
- // Move live_objects back into l->second
- // for filtering by the next region.
- live_objects->swap(l->second);
- live_objects->clear();
- }
- }
- // Now get and use live_objects from the final version of l->second:
- if (VLOG_IS_ON(11)) {
- for (LiveObjectsStack::const_iterator i = l->second.begin();
- i != l->second.end(); ++i) {
- RAW_VLOG(11, "Library live region at %p of %" PRIuPTR " bytes",
- i->ptr, i->size);
- }
- }
- live_objects->swap(l->second);
- IgnoreLiveObjectsLocked("in globals of\n ", l->first.c_str());
- }
- if (have_null_region_callers) {
- RAW_LOG(ERROR, "Have memory regions w/o callers: "
- "might report false leaks");
- }
- Allocator::DeleteAndNull(&library_live_objects);
- }
-}
-
-// Callback for TCMalloc_ListAllProcessThreads in IgnoreAllLiveObjectsLocked below
-// to test/verify that we have just the one main thread, in which case
-// we can do everything in that main thread,
-// so that CPU profiler can collect all its samples.
-// Returns the number of threads in the process.
-static int IsOneThread(void* parameter, int num_threads,
- pid_t* thread_pids, va_list ap) {
- if (num_threads != 1) {
- RAW_LOG(WARNING, "Have threads: Won't CPU-profile the bulk of leak "
- "checking work happening in IgnoreLiveThreadsLocked!");
- }
- TCMalloc_ResumeAllProcessThreads(num_threads, thread_pids);
- return num_threads;
-}
-
-// Dummy for IgnoreAllLiveObjectsLocked below.
-// Making it global helps with compiler warnings.
-static va_list dummy_ap;
-
-// static
-void HeapLeakChecker::IgnoreAllLiveObjectsLocked(const void* self_stack_top) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- RAW_CHECK(live_objects == NULL, "");
- live_objects = new(Allocator::Allocate(sizeof(LiveObjectsStack)))
- LiveObjectsStack;
- stack_tops = new(Allocator::Allocate(sizeof(StackTopSet))) StackTopSet;
- // reset the counts
- live_objects_total = 0;
- live_bytes_total = 0;
- // Reduce max_heap_object_size to FLAGS_heap_check_max_pointer_offset
- // for the time of leak check.
- // FLAGS_heap_check_max_pointer_offset caps max_heap_object_size
- // to manage reasonably low chances of random bytes
- // appearing to be pointing into large actually leaked heap objects.
- const size_t old_max_heap_object_size = max_heap_object_size;
- max_heap_object_size = (
- FLAGS_heap_check_max_pointer_offset != -1
- ? min(size_t(FLAGS_heap_check_max_pointer_offset), max_heap_object_size)
- : max_heap_object_size);
- // Record global data as live:
- if (FLAGS_heap_check_ignore_global_live) {
- library_live_objects =
- new(Allocator::Allocate(sizeof(LibraryLiveObjectsStacks)))
- LibraryLiveObjectsStacks;
- }
- // Ignore all thread stacks:
- thread_listing_status = CALLBACK_NOT_STARTED;
- bool need_to_ignore_non_thread_objects = true;
- self_thread_pid = getpid();
- self_thread_stack_top = self_stack_top;
- if (FLAGS_heap_check_ignore_thread_live) {
- // In case we are doing CPU profiling we'd like to do all the work
- // in the main thread, not in the special thread created by
- // TCMalloc_ListAllProcessThreads, so that CPU profiler can
- // collect all its samples. The machinery of
- // TCMalloc_ListAllProcessThreads conflicts with the CPU profiler
- // by also relying on signals and ::sigaction. We can do this
- // (run everything in the main thread) safely only if there's just
- // the main thread itself in our process. This variable reflects
- // these two conditions:
- bool want_and_can_run_in_main_thread =
- ProfilingIsEnabledForAllThreads() &&
- TCMalloc_ListAllProcessThreads(NULL, IsOneThread) == 1;
- // When the normal path of TCMalloc_ListAllProcessThreads below is taken,
- // we fully suspend the threads right here before any liveness checking
- // and keep them suspended for the whole time of liveness checking
- // inside of the IgnoreLiveThreadsLocked callback.
- // (The threads can't (de)allocate due to lock on the delete hook but
- // if not suspended they could still mess with the pointer
- // graph while we walk it).
- int r = want_and_can_run_in_main_thread
- ? IgnoreLiveThreadsLocked(NULL, 1, &self_thread_pid, dummy_ap)
- : TCMalloc_ListAllProcessThreads(NULL, IgnoreLiveThreadsLocked);
- need_to_ignore_non_thread_objects = r < 0;
- if (r < 0) {
- RAW_LOG(WARNING, "Thread finding failed with %d errno=%d", r, errno);
- if (thread_listing_status == CALLBACK_COMPLETED) {
- RAW_LOG(INFO, "Thread finding callback "
- "finished ok; hopefully everything is fine");
- need_to_ignore_non_thread_objects = false;
- } else if (thread_listing_status == CALLBACK_STARTED) {
- RAW_LOG(FATAL, "Thread finding callback was "
- "interrupted or crashed; can't fix this");
- } else { // CALLBACK_NOT_STARTED
- RAW_LOG(ERROR, "Could not find thread stacks. "
- "Will likely report false leak positives.");
- }
- } else if (r != 0) {
- RAW_LOG(ERROR, "Thread stacks not found for %d threads. "
- "Will likely report false leak positives.", r);
- } else {
- RAW_VLOG(11, "Thread stacks appear to be found for all threads");
- }
- } else {
- RAW_LOG(WARNING, "Not looking for thread stacks; "
- "objects reachable only from there "
- "will be reported as leaks");
- }
- // Do all other live data ignoring here if we did not do it
- // within thread listing callback with all threads stopped.
- if (need_to_ignore_non_thread_objects) {
- if (FLAGS_heap_check_ignore_global_live) {
- UseProcMapsLocked(RECORD_GLOBAL_DATA);
- }
- IgnoreNonThreadLiveObjectsLocked();
- }
- if (live_objects_total) {
- RAW_VLOG(10, "Ignoring %" PRId64 " reachable objects of %" PRId64 " bytes",
- live_objects_total, live_bytes_total);
- }
- // Free these: we made them here and heap_profile never saw them
- Allocator::DeleteAndNull(&live_objects);
- Allocator::DeleteAndNull(&stack_tops);
- max_heap_object_size = old_max_heap_object_size; // reset this var
-}
-
-// Alignment at which we should consider pointer positions
-// in IgnoreLiveObjectsLocked. Will normally use the value of
-// FLAGS_heap_check_pointer_source_alignment.
-static size_t pointer_source_alignment = kPointerSourceAlignment;
-// Global lock for HeapLeakChecker::DoNoLeaks
-// to protect pointer_source_alignment.
-static SpinLock alignment_checker_lock(SpinLock::LINKER_INITIALIZED);
-
-// This function changes the live bits in the heap_profile-table's state:
-// we only record the live objects to be skipped.
-//
-// When checking if a byte sequence points to a heap object we use
-// HeapProfileTable::FindInsideAlloc to handle both pointers to
-// the start and inside of heap-allocated objects.
-// The "inside" case needs to be checked to support
-// at least the following relatively common cases:
-// - C++ arrays allocated with new FooClass[size] for classes
-// with destructors have their size recorded in a sizeof(int) field
-// before the place normal pointers point to.
-// - basic_string<>-s for e.g. the C++ library of gcc 3.4
-// have the meta-info in basic_string<...>::_Rep recorded
-// before the place normal pointers point to.
-// - Multiple-inherited objects have their pointers when cast to
-// different base classes pointing inside of the actually
-// allocated object.
-// - Sometimes reachability pointers point to member objects of heap objects,
-// and then those member objects point to the full heap object.
-// - Third party UnicodeString: it stores a 32-bit refcount
-// (in both 32-bit and 64-bit binaries) as the first uint32
-// in the allocated memory and a normal pointer points at
-// the second uint32 behind the refcount.
-// By finding these additional objects here
-// we slightly increase the chance to mistake random memory bytes
-// for a pointer and miss a leak in a particular run of a binary.
-//
-/*static*/ void HeapLeakChecker::IgnoreLiveObjectsLocked(const char* name,
- const char* name2) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- int64 live_object_count = 0;
- int64 live_byte_count = 0;
- while (!live_objects->empty()) {
- const char* object =
- reinterpret_cast<const char*>(live_objects->back().ptr);
- size_t size = live_objects->back().size;
- const ObjectPlacement place = live_objects->back().place;
- live_objects->pop_back();
- if (place == MUST_BE_ON_HEAP && heap_profile->MarkAsLive(object)) {
- live_object_count += 1;
- live_byte_count += size;
- }
- RAW_VLOG(13, "Looking for heap pointers in %p of %" PRIuS " bytes",
- object, size);
- const char* const whole_object = object;
- size_t const whole_size = size;
- // Try interpretting any byte sequence in object,size as a heap pointer:
- const size_t remainder = AsInt(object) % pointer_source_alignment;
- if (remainder) {
- object += pointer_source_alignment - remainder;
- if (size >= pointer_source_alignment - remainder) {
- size -= pointer_source_alignment - remainder;
- } else {
- size = 0;
- }
- }
- if (size < sizeof(void*)) continue;
-
-#ifdef NO_FRAME_POINTER
- // Frame pointer omission requires us to use libunwind, which uses direct
- // mmap and munmap system calls, and that needs special handling.
- if (name2 == kUnnamedProcSelfMapEntry) {
- static const uintptr_t page_mask = ~(getpagesize() - 1);
- const uintptr_t addr = reinterpret_cast<uintptr_t>(object);
- if ((addr & page_mask) == 0 && (size & page_mask) == 0) {
- // This is an object we slurped from /proc/self/maps.
- // It may or may not be readable at this point.
- //
- // In case all the above conditions made a mistake, and the object is
- // not related to libunwind, we also verify that it's not readable
- // before ignoring it.
- if (msync(const_cast<char*>(object), size, MS_ASYNC) != 0) {
- // Skip unreadable object, so we don't crash trying to sweep it.
- RAW_VLOG(0, "Ignoring inaccessible object [%p, %p) "
- "(msync error %d (%s))",
- object, object + size, errno, strerror(errno));
- continue;
- }
- }
- }
-#endif
-
- const char* const max_object = object + size - sizeof(void*);
- while (object <= max_object) {
- // potentially unaligned load:
- const uintptr_t addr = *reinterpret_cast<const uintptr_t*>(object);
- // Do fast check before the more expensive HaveOnHeapLocked lookup:
- // this code runs for all memory words that are potentially pointers:
- const bool can_be_on_heap =
- // Order tests by the likelyhood of the test failing in 64/32 bit modes.
- // Yes, this matters: we either lose 5..6% speed in 32 bit mode
- // (which is already slower) or by a factor of 1.5..1.91 in 64 bit mode.
- // After the alignment test got dropped the above performance figures
- // must have changed; might need to revisit this.
-#if defined(__x86_64__)
- addr <= max_heap_address && // <= is for 0-sized object with max addr
- min_heap_address <= addr;
-#else
- min_heap_address <= addr &&
- addr <= max_heap_address; // <= is for 0-sized object with max addr
-#endif
- if (can_be_on_heap) {
- const void* ptr = reinterpret_cast<const void*>(addr);
- // Too expensive (inner loop): manually uncomment when debugging:
- // RAW_VLOG(17, "Trying pointer to %p at %p", ptr, object);
- size_t object_size;
- if (HaveOnHeapLocked(&ptr, &object_size) &&
- heap_profile->MarkAsLive(ptr)) {
- // We take the (hopefully low) risk here of encountering by accident
- // a byte sequence in memory that matches an address of
- // a heap object which is in fact leaked.
- // I.e. in very rare and probably not repeatable/lasting cases
- // we might miss some real heap memory leaks.
- RAW_VLOG(14, "Found pointer to %p of %" PRIuS " bytes at %p "
- "inside %p of size %" PRIuS "",
- ptr, object_size, object, whole_object, whole_size);
- if (VLOG_IS_ON(15)) {
- // log call stacks to help debug how come something is not a leak
- HeapProfileTable::AllocInfo alloc;
- if (!heap_profile->FindAllocDetails(ptr, &alloc)) {
- RAW_LOG(FATAL, "FindAllocDetails failed on ptr %p", ptr);
- }
- RAW_LOG(INFO, "New live %p object's alloc stack:", ptr);
- for (int i = 0; i < alloc.stack_depth; ++i) {
- RAW_LOG(INFO, " @ %p", alloc.call_stack[i]);
- }
- }
- live_object_count += 1;
- live_byte_count += object_size;
- live_objects->push_back(AllocObject(ptr, object_size,
- IGNORED_ON_HEAP));
- }
- }
- object += pointer_source_alignment;
- }
- }
- live_objects_total += live_object_count;
- live_bytes_total += live_byte_count;
- if (live_object_count) {
- RAW_VLOG(10, "Removed %" PRId64 " live heap objects of %" PRId64 " bytes: %s%s",
- live_object_count, live_byte_count, name, name2);
- }
-}
-
-//----------------------------------------------------------------------
-// HeapLeakChecker leak check disabling components
-//----------------------------------------------------------------------
-
-// static
-void HeapLeakChecker::DisableChecksIn(const char* pattern) {
- RAW_LOG(WARNING, "DisableChecksIn(%s) is ignored", pattern);
-}
-
-// static
-void HeapLeakChecker::DoIgnoreObject(const void* ptr) {
- SpinLockHolder l(&heap_checker_lock);
- if (!heap_checker_on) return;
- size_t object_size;
- if (!HaveOnHeapLocked(&ptr, &object_size)) {
- RAW_LOG(ERROR, "No live heap object at %p to ignore", ptr);
- } else {
- RAW_VLOG(10, "Going to ignore live object at %p of %" PRIuS " bytes",
- ptr, object_size);
- if (ignored_objects == NULL) {
- ignored_objects = new(Allocator::Allocate(sizeof(IgnoredObjectsMap)))
- IgnoredObjectsMap;
- }
- if (!ignored_objects->insert(make_pair(AsInt(ptr), object_size)).second) {
- RAW_LOG(WARNING, "Object at %p is already being ignored", ptr);
- }
- }
-}
-
-// static
-void HeapLeakChecker::UnIgnoreObject(const void* ptr) {
- SpinLockHolder l(&heap_checker_lock);
- if (!heap_checker_on) return;
- size_t object_size;
- if (!HaveOnHeapLocked(&ptr, &object_size)) {
- RAW_LOG(FATAL, "No live heap object at %p to un-ignore", ptr);
- } else {
- bool found = false;
- if (ignored_objects) {
- IgnoredObjectsMap::iterator object = ignored_objects->find(AsInt(ptr));
- if (object != ignored_objects->end() && object_size == object->second) {
- ignored_objects->erase(object);
- found = true;
- RAW_VLOG(10, "Now not going to ignore live object "
- "at %p of %" PRIuS " bytes", ptr, object_size);
- }
- }
- if (!found) RAW_LOG(FATAL, "Object at %p has not been ignored", ptr);
- }
-}
-
-//----------------------------------------------------------------------
-// HeapLeakChecker non-static functions
-//----------------------------------------------------------------------
-
-char* HeapLeakChecker::MakeProfileNameLocked() {
- RAW_DCHECK(lock_->IsHeld(), "");
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- const int len = profile_name_prefix->size() + strlen(name_) + 5 +
- strlen(HeapProfileTable::kFileExt) + 1;
- char* file_name = reinterpret_cast<char*>(Allocator::Allocate(len));
- snprintf(file_name, len, "%s.%s-end%s",
- profile_name_prefix->c_str(), name_,
- HeapProfileTable::kFileExt);
- return file_name;
-}
-
-void HeapLeakChecker::Create(const char *name, bool make_start_snapshot) {
- SpinLockHolder l(lock_);
- name_ = NULL; // checker is inactive
- start_snapshot_ = NULL;
- has_checked_ = false;
- inuse_bytes_increase_ = 0;
- inuse_allocs_increase_ = 0;
- keep_profiles_ = false;
- char* n = new char[strlen(name) + 1]; // do this before we lock
- IgnoreObject(n); // otherwise it might be treated as live due to our stack
- { // Heap activity in other threads is paused for this whole scope.
- SpinLockHolder al(&alignment_checker_lock);
- SpinLockHolder hl(&heap_checker_lock);
- MemoryRegionMap::LockHolder ml;
- if (heap_checker_on && profile_name_prefix != NULL) {
- RAW_DCHECK(strchr(name, '/') == NULL, "must be a simple name");
- memcpy(n, name, strlen(name) + 1);
- name_ = n; // checker is active
- if (make_start_snapshot) {
- start_snapshot_ = heap_profile->TakeSnapshot();
- }
-
- const HeapProfileTable::Stats& t = heap_profile->total();
- const size_t start_inuse_bytes = t.alloc_size - t.free_size;
- const size_t start_inuse_allocs = t.allocs - t.frees;
- RAW_VLOG(10, "Start check \"%s\" profile: %" PRIuS " bytes "
- "in %" PRIuS " objects",
- name_, start_inuse_bytes, start_inuse_allocs);
- } else {
- RAW_LOG(WARNING, "Heap checker is not active, "
- "hence checker \"%s\" will do nothing!", name);
- RAW_LOG(WARNING, "To activate set the HEAPCHECK environment variable.\n");
- }
- }
- if (name_ == NULL) {
- UnIgnoreObject(n);
- delete[] n; // must be done after we unlock
- }
-}
-
-HeapLeakChecker::HeapLeakChecker(const char *name) : lock_(new SpinLock) {
- RAW_DCHECK(strcmp(name, "_main_") != 0, "_main_ is reserved");
- Create(name, true/*create start_snapshot_*/);
-}
-
-HeapLeakChecker::HeapLeakChecker() : lock_(new SpinLock) {
- if (FLAGS_heap_check_before_constructors) {
- // We want to check for leaks of objects allocated during global
- // constructors (i.e., objects allocated already). So we do not
- // create a baseline snapshot and hence check for leaks of objects
- // that may have already been created.
- Create("_main_", false);
- } else {
- // We want to ignore leaks of objects allocated during global
- // constructors (i.e., objects allocated already). So we snapshot
- // the current heap contents and use them as a baseline that is
- // not reported by the leak checker.
- Create("_main_", true);
- }
-}
-
-ssize_t HeapLeakChecker::BytesLeaked() const {
- SpinLockHolder l(lock_);
- if (!has_checked_) {
- RAW_LOG(FATAL, "*NoLeaks|SameHeap must execute before this call");
- }
- return inuse_bytes_increase_;
-}
-
-ssize_t HeapLeakChecker::ObjectsLeaked() const {
- SpinLockHolder l(lock_);
- if (!has_checked_) {
- RAW_LOG(FATAL, "*NoLeaks|SameHeap must execute before this call");
- }
- return inuse_allocs_increase_;
-}
-
-// Save pid of main thread for using in naming dump files
-static int32 main_thread_pid = getpid();
-#ifdef HAVE_PROGRAM_INVOCATION_NAME
-#ifdef __UCLIBC__
-extern const char* program_invocation_name;
-extern const char* program_invocation_short_name;
-#else
-extern char* program_invocation_name;
-extern char* program_invocation_short_name;
-#endif
-static const char* invocation_name() { return program_invocation_short_name; }
-static string invocation_path() { return program_invocation_name; }
-#else
-static const char* invocation_name() { return "<your binary>"; }
-static string invocation_path() { return "<your binary>"; }
-#endif
-
-// Prints commands that users can run to get more information
-// about the reported leaks.
-static void SuggestPprofCommand(const char* pprof_file_arg) {
- // Extra help information to print for the user when the test is
- // being run in a way where the straightforward pprof command will
- // not suffice.
- string extra_help;
-
- // Common header info to print for remote runs
- const string remote_header =
- "This program is being executed remotely and therefore the pprof\n"
- "command printed above will not work. Either run this program\n"
- "locally, or adjust the pprof command as follows to allow it to\n"
- "work on your local machine:\n";
-
- // Extra command for fetching remote data
- string fetch_cmd;
-
- RAW_LOG(WARNING,
- "\n\n"
- "If the preceding stack traces are not enough to find "
- "the leaks, try running THIS shell command:\n\n"
- "%s%s %s \"%s\" --inuse_objects --lines --heapcheck "
- " --edgefraction=1e-10 --nodefraction=1e-10 --gv\n"
- "\n"
- "%s"
- "If you are still puzzled about why the leaks are "
- "there, try rerunning this program with "
- "HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with "
- "HEAP_CHECK_MAX_POINTER_OFFSET=-1\n"
- "If the leak report occurs in a small fraction of runs, "
- "try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB "
- "or with TCMALLOC_RECLAIM_MEMORY=false, " // only works for debugalloc
- "it might help find leaks more repeatably\n",
- fetch_cmd.c_str(),
- "pprof", // works as long as pprof is on your path
- invocation_path().c_str(),
- pprof_file_arg,
- extra_help.c_str()
- );
-}
-
-bool HeapLeakChecker::DoNoLeaks(ShouldSymbolize should_symbolize) {
- SpinLockHolder l(lock_);
- // The locking also helps us keep the messages
- // for the two checks close together.
- SpinLockHolder al(&alignment_checker_lock);
-
- // thread-safe: protected by alignment_checker_lock
- static bool have_disabled_hooks_for_symbolize = false;
- // Once we've checked for leaks and symbolized the results once, it's
- // not safe to do it again. This is because in order to symbolize
- // safely, we had to disable all the malloc hooks here, so we no
- // longer can be confident we've collected all the data we need.
- if (have_disabled_hooks_for_symbolize) {
- RAW_LOG(FATAL, "Must not call heap leak checker manually after "
- " program-exit's automatic check.");
- }
-
- HeapProfileTable::Snapshot* leaks = NULL;
- char* pprof_file = NULL;
-
- {
- // Heap activity in other threads is paused during this function
- // (i.e. until we got all profile difference info).
- SpinLockHolder hl(&heap_checker_lock);
- if (heap_checker_on == false) {
- if (name_ != NULL) { // leak checking enabled when created the checker
- RAW_LOG(WARNING, "Heap leak checker got turned off after checker "
- "\"%s\" has been created, no leak check is being done for it!",
- name_);
- }
- return true;
- }
-
- // Update global_region_caller_ranges. They may need to change since
- // e.g. initialization because shared libraries might have been loaded or
- // unloaded.
- Allocator::DeleteAndNullIfNot(&global_region_caller_ranges);
- ProcMapsResult pm_result = UseProcMapsLocked(DISABLE_LIBRARY_ALLOCS);
- RAW_CHECK(pm_result == PROC_MAPS_USED, "");
-
- // Keep track of number of internally allocated objects so we
- // can detect leaks in the heap-leak-checket itself
- const int initial_allocs = Allocator::alloc_count();
-
- if (name_ == NULL) {
- RAW_LOG(FATAL, "Heap leak checker must not be turned on "
- "after construction of a HeapLeakChecker");
- }
-
- MemoryRegionMap::LockHolder ml;
- int a_local_var; // Use our stack ptr to make stack data live:
-
- // Make the heap profile, other threads are locked out.
- HeapProfileTable::Snapshot* base =
- reinterpret_cast<HeapProfileTable::Snapshot*>(start_snapshot_);
- RAW_DCHECK(FLAGS_heap_check_pointer_source_alignment > 0, "");
- pointer_source_alignment = FLAGS_heap_check_pointer_source_alignment;
- IgnoreAllLiveObjectsLocked(&a_local_var);
- leaks = heap_profile->NonLiveSnapshot(base);
-
- inuse_bytes_increase_ = static_cast<ssize_t>(leaks->total().alloc_size);
- inuse_allocs_increase_ = static_cast<ssize_t>(leaks->total().allocs);
- if (leaks->Empty()) {
- heap_profile->ReleaseSnapshot(leaks);
- leaks = NULL;
-
- // We can only check for internal leaks along the no-user-leak
- // path since in the leak path we temporarily release
- // heap_checker_lock and another thread can come in and disturb
- // allocation counts.
- if (Allocator::alloc_count() != initial_allocs) {
- RAW_LOG(FATAL, "Internal HeapChecker leak of %d objects ; %d -> %d",
- Allocator::alloc_count() - initial_allocs,
- initial_allocs, Allocator::alloc_count());
- }
- } else if (FLAGS_heap_check_test_pointer_alignment) {
- if (pointer_source_alignment == 1) {
- RAW_LOG(WARNING, "--heap_check_test_pointer_alignment has no effect: "
- "--heap_check_pointer_source_alignment was already set to 1");
- } else {
- // Try with reduced pointer aligment
- pointer_source_alignment = 1;
- IgnoreAllLiveObjectsLocked(&a_local_var);
- HeapProfileTable::Snapshot* leaks_wo_align =
- heap_profile->NonLiveSnapshot(base);
- pointer_source_alignment = FLAGS_heap_check_pointer_source_alignment;
- if (leaks_wo_align->Empty()) {
- RAW_LOG(WARNING, "Found no leaks without pointer alignment: "
- "something might be placing pointers at "
- "unaligned addresses! This needs to be fixed.");
- } else {
- RAW_LOG(INFO, "Found leaks without pointer alignment as well: "
- "unaligned pointers must not be the cause of leaks.");
- RAW_LOG(INFO, "--heap_check_test_pointer_alignment did not help "
- "to diagnose the leaks.");
- }
- heap_profile->ReleaseSnapshot(leaks_wo_align);
- }
- }
-
- if (leaks != NULL) {
- pprof_file = MakeProfileNameLocked();
- }
- }
-
- has_checked_ = true;
- if (leaks == NULL) {
- if (FLAGS_heap_check_max_pointer_offset == -1) {
- RAW_LOG(WARNING,
- "Found no leaks without max_pointer_offset restriction: "
- "it's possible that the default value of "
- "heap_check_max_pointer_offset flag is too low. "
- "Do you use pointers with larger than that offsets "
- "pointing in the middle of heap-allocated objects?");
- }
- const HeapProfileTable::Stats& stats = heap_profile->total();
- RAW_VLOG(heap_checker_info_level,
- "No leaks found for check \"%s\" "
- "(but no 100%% guarantee that there aren't any): "
- "found %" PRId64 " reachable heap objects of %" PRId64 " bytes",
- name_,
- int64(stats.allocs - stats.frees),
- int64(stats.alloc_size - stats.free_size));
- } else {
- if (should_symbolize == SYMBOLIZE) {
- // To turn addresses into symbols, we need to fork, which is a
- // problem if both parent and child end up trying to call the
- // same malloc-hooks we've set up, at the same time. To avoid
- // trouble, we turn off the hooks before symbolizing. Note that
- // this makes it unsafe to ever leak-report again! Luckily, we
- // typically only want to report once in a program's run, at the
- // very end.
- if (MallocHook::GetNewHook() == NewHook)
- MallocHook::SetNewHook(NULL);
- if (MallocHook::GetDeleteHook() == DeleteHook)
- MallocHook::SetDeleteHook(NULL);
- MemoryRegionMap::Shutdown();
- // Make sure all the hooks really got unset:
- RAW_CHECK(MallocHook::GetNewHook() == NULL, "");
- RAW_CHECK(MallocHook::GetDeleteHook() == NULL, "");
- RAW_CHECK(MallocHook::GetMmapHook() == NULL, "");
- RAW_CHECK(MallocHook::GetSbrkHook() == NULL, "");
- have_disabled_hooks_for_symbolize = true;
- leaks->ReportLeaks(name_, pprof_file, true); // true = should_symbolize
- } else {
- leaks->ReportLeaks(name_, pprof_file, false);
- }
- if (FLAGS_heap_check_identify_leaks) {
- leaks->ReportIndividualObjects();
- }
-
- SuggestPprofCommand(pprof_file);
-
- {
- SpinLockHolder hl(&heap_checker_lock);
- heap_profile->ReleaseSnapshot(leaks);
- Allocator::Free(pprof_file);
- }
- }
-
- return (leaks == NULL);
-}
-
-HeapLeakChecker::~HeapLeakChecker() {
- if (name_ != NULL) { // had leak checking enabled when created the checker
- if (!has_checked_) {
- RAW_LOG(FATAL, "Some *NoLeaks|SameHeap method"
- " must be called on any created HeapLeakChecker");
- }
-
- // Deallocate any snapshot taken at start
- if (start_snapshot_ != NULL) {
- SpinLockHolder l(&heap_checker_lock);
- heap_profile->ReleaseSnapshot(
- reinterpret_cast<HeapProfileTable::Snapshot*>(start_snapshot_));
- }
-
- UnIgnoreObject(name_);
- delete[] name_;
- name_ = NULL;
- }
- delete lock_;
-}
-
-//----------------------------------------------------------------------
-// HeapLeakChecker overall heap check components
-//----------------------------------------------------------------------
-
-// static
-bool HeapLeakChecker::IsActive() {
- SpinLockHolder l(&heap_checker_lock);
- return heap_checker_on;
-}
-
-vector<HeapCleaner::void_function>* HeapCleaner::heap_cleanups_ = NULL;
-
-// When a HeapCleaner object is intialized, add its function to the static list
-// of cleaners to be run before leaks checking.
-HeapCleaner::HeapCleaner(void_function f) {
- if (heap_cleanups_ == NULL)
- heap_cleanups_ = new vector<HeapCleaner::void_function>;
- heap_cleanups_->push_back(f);
-}
-
-// Run all of the cleanup functions and delete the vector.
-void HeapCleaner::RunHeapCleanups() {
- if (!heap_cleanups_)
- return;
- for (int i = 0; i < heap_cleanups_->size(); i++) {
- void (*f)(void) = (*heap_cleanups_)[i];
- f();
- }
- delete heap_cleanups_;
- heap_cleanups_ = NULL;
-}
-
-// Program exit heap cleanup registered as a module object destructor.
-// Will not get executed when we crash on a signal.
-//
-void HeapLeakChecker_RunHeapCleanups() {
- if (FLAGS_heap_check == "local") // don't check heap in this mode
- return;
- { SpinLockHolder l(&heap_checker_lock);
- // can get here (via forks?) with other pids
- if (heap_checker_pid != getpid()) return;
- }
- HeapCleaner::RunHeapCleanups();
- if (!FLAGS_heap_check_after_destructors) HeapLeakChecker::DoMainHeapCheck();
-}
-
-static bool internal_init_start_has_run = false;
-
-// Called exactly once, before main() (but hopefully just before).
-// This picks a good unique name for the dumped leak checking heap profiles.
-//
-// Because we crash when InternalInitStart is called more than once,
-// it's fine that we hold heap_checker_lock only around pieces of
-// this function: this is still enough for thread-safety w.r.t. other functions
-// of this module.
-// We can't hold heap_checker_lock throughout because it would deadlock
-// on a memory allocation since our new/delete hooks can be on.
-//
-void HeapLeakChecker_InternalInitStart() {
- { SpinLockHolder l(&heap_checker_lock);
- RAW_CHECK(!internal_init_start_has_run,
- "Heap-check constructor called twice. Perhaps you both linked"
- " in the heap checker, and also used LD_PRELOAD to load it?");
- internal_init_start_has_run = true;
-
-#ifdef ADDRESS_SANITIZER
- // AddressSanitizer's custom malloc conflicts with HeapChecker.
- FLAGS_heap_check = "";
-#endif
-
- if (FLAGS_heap_check.empty()) {
- // turns out we do not need checking in the end; can stop profiling
- HeapLeakChecker::TurnItselfOffLocked();
- return;
- } else if (RunningOnValgrind()) {
- // There is no point in trying -- we'll just fail.
- RAW_LOG(WARNING, "Can't run under Valgrind; will turn itself off");
- HeapLeakChecker::TurnItselfOffLocked();
- return;
- }
- }
-
- // Changing this to false can be useful when debugging heap-checker itself:
- if (!FLAGS_heap_check_run_under_gdb && IsDebuggerAttached()) {
- RAW_LOG(WARNING, "Someone is ptrace()ing us; will turn itself off");
- SpinLockHolder l(&heap_checker_lock);
- HeapLeakChecker::TurnItselfOffLocked();
- return;
- }
-
- { SpinLockHolder l(&heap_checker_lock);
- if (!constructor_heap_profiling) {
- RAW_LOG(FATAL, "Can not start so late. You have to enable heap checking "
- "with HEAPCHECK=<mode>.");
- }
- }
-
- // Set all flags
- RAW_DCHECK(FLAGS_heap_check_pointer_source_alignment > 0, "");
- if (FLAGS_heap_check == "minimal") {
- // The least we can check.
- FLAGS_heap_check_before_constructors = false; // from after main
- // (ignore more)
- FLAGS_heap_check_after_destructors = false; // to after cleanup
- // (most data is live)
- FLAGS_heap_check_ignore_thread_live = true; // ignore all live
- FLAGS_heap_check_ignore_global_live = true; // ignore all live
- } else if (FLAGS_heap_check == "normal") {
- // Faster than 'minimal' and not much stricter.
- FLAGS_heap_check_before_constructors = true; // from no profile (fast)
- FLAGS_heap_check_after_destructors = false; // to after cleanup
- // (most data is live)
- FLAGS_heap_check_ignore_thread_live = true; // ignore all live
- FLAGS_heap_check_ignore_global_live = true; // ignore all live
- } else if (FLAGS_heap_check == "strict") {
- // A bit stricter than 'normal': global destructors must fully clean up
- // after themselves if they are present.
- FLAGS_heap_check_before_constructors = true; // from no profile (fast)
- FLAGS_heap_check_after_destructors = true; // to after destructors
- // (less data live)
- FLAGS_heap_check_ignore_thread_live = true; // ignore all live
- FLAGS_heap_check_ignore_global_live = true; // ignore all live
- } else if (FLAGS_heap_check == "draconian") {
- // Drop not very portable and not very exact live heap flooding.
- FLAGS_heap_check_before_constructors = true; // from no profile (fast)
- FLAGS_heap_check_after_destructors = true; // to after destructors
- // (need them)
- FLAGS_heap_check_ignore_thread_live = false; // no live flood (stricter)
- FLAGS_heap_check_ignore_global_live = false; // no live flood (stricter)
- } else if (FLAGS_heap_check == "as-is") {
- // do nothing: use other flags as is
- } else if (FLAGS_heap_check == "local") {
- // do nothing
- } else {
- RAW_LOG(FATAL, "Unsupported heap_check flag: %s",
- FLAGS_heap_check.c_str());
- }
- // FreeBSD doesn't seem to honor atexit execution order:
- // http://code.google.com/p/gperftools/issues/detail?id=375
- // Since heap-checking before destructors depends on atexit running
- // at the right time, on FreeBSD we always check after, even in the
- // less strict modes. This just means FreeBSD is always a bit
- // stricter in its checking than other OSes.
- // This now appears to be the case in other OSes as well;
- // so always check afterwards.
- FLAGS_heap_check_after_destructors = true;
-
- { SpinLockHolder l(&heap_checker_lock);
- RAW_DCHECK(heap_checker_pid == getpid(), "");
- heap_checker_on = true;
- RAW_DCHECK(heap_profile, "");
- HeapLeakChecker::ProcMapsResult pm_result = HeapLeakChecker::UseProcMapsLocked(HeapLeakChecker::DISABLE_LIBRARY_ALLOCS);
- // might neeed to do this more than once
- // if one later dynamically loads libraries that we want disabled
- if (pm_result != HeapLeakChecker::PROC_MAPS_USED) { // can't function
- HeapLeakChecker::TurnItselfOffLocked();
- return;
- }
- }
-
- // make a good place and name for heap profile leak dumps
- string* profile_prefix =
- new string(FLAGS_heap_check_dump_directory + "/" + invocation_name());
-
- // Finalize prefix for dumping leak checking profiles.
- const int32 our_pid = getpid(); // safest to call getpid() outside lock
- { SpinLockHolder l(&heap_checker_lock);
- // main_thread_pid might still be 0 if this function is being called before
- // global constructors. In that case, our pid *is* the main pid.
- if (main_thread_pid == 0)
- main_thread_pid = our_pid;
- }
- char pid_buf[15];
- snprintf(pid_buf, sizeof(pid_buf), ".%d", main_thread_pid);
- *profile_prefix += pid_buf;
- { SpinLockHolder l(&heap_checker_lock);
- RAW_DCHECK(profile_name_prefix == NULL, "");
- profile_name_prefix = profile_prefix;
- }
-
- // Make sure new/delete hooks are installed properly
- // and heap profiler is indeed able to keep track
- // of the objects being allocated.
- // We test this to make sure we are indeed checking for leaks.
- char* test_str = new char[5];
- size_t size;
- { SpinLockHolder l(&heap_checker_lock);
- RAW_CHECK(heap_profile->FindAlloc(test_str, &size),
- "our own new/delete not linked?");
- }
- delete[] test_str;
- { SpinLockHolder l(&heap_checker_lock);
- // This check can fail when it should not if another thread allocates
- // into this same spot right this moment,
- // which is unlikely since this code runs in InitGoogle.
- RAW_CHECK(!heap_profile->FindAlloc(test_str, &size),
- "our own new/delete not linked?");
- }
- // If we crash in the above code, it probably means that
- // "nm <this_binary> | grep new" will show that tcmalloc's new/delete
- // implementation did not get linked-in into this binary
- // (i.e. nm will list __builtin_new and __builtin_vec_new as undefined).
- // If this happens, it is a BUILD bug to be fixed.
-
- RAW_VLOG(heap_checker_info_level,
- "WARNING: Perftools heap leak checker is active "
- "-- Performance may suffer");
-
- if (FLAGS_heap_check != "local") {
- HeapLeakChecker* main_hc = new HeapLeakChecker();
- SpinLockHolder l(&heap_checker_lock);
- RAW_DCHECK(main_heap_checker == NULL,
- "Repeated creation of main_heap_checker");
- main_heap_checker = main_hc;
- do_main_heap_check = true;
- }
-
- { SpinLockHolder l(&heap_checker_lock);
- RAW_CHECK(heap_checker_on && constructor_heap_profiling,
- "Leak checking is expected to be fully turned on now");
- }
-
- // For binaries built in debug mode, this will set release queue of
- // debugallocation.cc to 100M to make it less likely for real leaks to
- // be hidden due to reuse of heap memory object addresses.
- // Running a test with --malloc_reclaim_memory=0 would help find leaks even
- // better, but the test might run out of memory as a result.
- // The scenario is that a heap object at address X is allocated and freed,
- // but some other data-structure still retains a pointer to X.
- // Then the same heap memory is used for another object, which is leaked,
- // but the leak is not noticed due to the pointer to the original object at X.
- // TODO(csilvers): support this in some manner.
-#if 0
- SetCommandLineOptionWithMode("max_free_queue_size", "104857600", // 100M
- SET_FLAG_IF_DEFAULT);
-#endif
-}
-
-// We want this to run early as well, but not so early as
-// ::BeforeConstructors (we want flag assignments to have already
-// happened, for instance). Initializer-registration does the trick.
-REGISTER_MODULE_INITIALIZER(init_start, HeapLeakChecker_InternalInitStart());
-REGISTER_MODULE_DESTRUCTOR(init_start, HeapLeakChecker_RunHeapCleanups());
-
-// static
-bool HeapLeakChecker::NoGlobalLeaksMaybeSymbolize(
- ShouldSymbolize should_symbolize) {
- // we never delete or change main_heap_checker once it's set:
- HeapLeakChecker* main_hc = GlobalChecker();
- if (main_hc) {
- RAW_VLOG(10, "Checking for whole-program memory leaks");
- return main_hc->DoNoLeaks(should_symbolize);
- }
- return true;
-}
-
-// static
-bool HeapLeakChecker::DoMainHeapCheck() {
- if (FLAGS_heap_check_delay_seconds > 0) {
- sleep(FLAGS_heap_check_delay_seconds);
- }
- { SpinLockHolder l(&heap_checker_lock);
- if (!do_main_heap_check) return false;
- RAW_DCHECK(heap_checker_pid == getpid(), "");
- do_main_heap_check = false; // will do it now; no need to do it more
- }
-
- // The program is over, so it's safe to symbolize addresses (which
- // requires a fork) because no serious work is expected to be done
- // after this. Symbolizing is really useful -- knowing what
- // function has a leak is better than knowing just an address --
- // and while we can only safely symbolize once in a program run,
- // now is the time (after all, there's no "later" that would be better).
- if (!NoGlobalLeaksMaybeSymbolize(SYMBOLIZE)) {
- if (FLAGS_heap_check_identify_leaks) {
- RAW_LOG(FATAL, "Whole-program memory leaks found.");
- }
- RAW_LOG(ERROR, "Exiting with error code (instead of crashing) "
- "because of whole-program memory leaks");
- _exit(1); // we don't want to call atexit() routines!
- }
- return true;
-}
-
-// static
-HeapLeakChecker* HeapLeakChecker::GlobalChecker() {
- SpinLockHolder l(&heap_checker_lock);
- return main_heap_checker;
-}
-
-// static
-bool HeapLeakChecker::NoGlobalLeaks() {
- // symbolizing requires a fork, which isn't safe to do in general.
- return NoGlobalLeaksMaybeSymbolize(DO_NOT_SYMBOLIZE);
-}
-
-// static
-void HeapLeakChecker::CancelGlobalCheck() {
- SpinLockHolder l(&heap_checker_lock);
- if (do_main_heap_check) {
- RAW_VLOG(heap_checker_info_level,
- "Canceling the automatic at-exit whole-program memory leak check");
- do_main_heap_check = false;
- }
-}
-
-// static
-void HeapLeakChecker::BeforeConstructorsLocked() {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- RAW_CHECK(!constructor_heap_profiling,
- "BeforeConstructorsLocked called multiple times");
-#ifdef ADDRESS_SANITIZER
- // AddressSanitizer's custom malloc conflicts with HeapChecker.
- return;
-#endif
- // Set hooks early to crash if 'new' gets called before we make heap_profile,
- // and make sure no other hooks existed:
- RAW_CHECK(MallocHook::AddNewHook(&NewHook), "");
- RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), "");
- constructor_heap_profiling = true;
- MemoryRegionMap::Init(1, /* use_buckets */ false);
- // Set up MemoryRegionMap with (at least) one caller stack frame to record
- // (important that it's done before HeapProfileTable creation below).
- Allocator::Init();
- RAW_CHECK(heap_profile == NULL, "");
- heap_profile = new(Allocator::Allocate(sizeof(HeapProfileTable)))
- HeapProfileTable(&Allocator::Allocate, &Allocator::Free,
- /* profile_mmap */ false);
- RAW_VLOG(10, "Starting tracking the heap");
- heap_checker_on = true;
-}
-
-// static
-void HeapLeakChecker::TurnItselfOffLocked() {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- // Set FLAGS_heap_check to "", for users who test for it
- if (!FLAGS_heap_check.empty()) // be a noop in the common case
- FLAGS_heap_check.clear(); // because clear() could allocate memory
- if (constructor_heap_profiling) {
- RAW_CHECK(heap_checker_on, "");
- RAW_VLOG(heap_checker_info_level, "Turning perftools heap leak checking off");
- heap_checker_on = false;
- // Unset our hooks checking they were set:
- RAW_CHECK(MallocHook::RemoveNewHook(&NewHook), "");
- RAW_CHECK(MallocHook::RemoveDeleteHook(&DeleteHook), "");
- Allocator::DeleteAndNull(&heap_profile);
- // free our optional global data:
- Allocator::DeleteAndNullIfNot(&ignored_objects);
- Allocator::DeleteAndNullIfNot(&disabled_ranges);
- Allocator::DeleteAndNullIfNot(&global_region_caller_ranges);
- Allocator::Shutdown();
- MemoryRegionMap::Shutdown();
- }
- RAW_CHECK(!heap_checker_on, "");
-}
-
-extern bool heap_leak_checker_bcad_variable; // in heap-checker-bcad.cc
-
-static bool has_called_before_constructors = false;
-
-// TODO(maxim): inline this function with
-// MallocHook_InitAtFirstAllocation_HeapLeakChecker, and also rename
-// HeapLeakChecker::BeforeConstructorsLocked.
-void HeapLeakChecker_BeforeConstructors() {
- SpinLockHolder l(&heap_checker_lock);
- // We can be called from several places: the first mmap/sbrk/alloc call
- // or the first global c-tor from heap-checker-bcad.cc:
- // Do not re-execute initialization:
- if (has_called_before_constructors) return;
- has_called_before_constructors = true;
-
- heap_checker_pid = getpid(); // set it always
- heap_leak_checker_bcad_variable = true;
- // just to reference it, so that heap-checker-bcad.o is linked in
-
- // This function can be called *very* early, before the normal
- // global-constructor that sets FLAGS_verbose. Set it manually now,
- // so the RAW_LOG messages here are controllable.
- const char* verbose_str = GetenvBeforeMain("PERFTOOLS_VERBOSE");
- if (verbose_str && atoi(verbose_str)) { // different than the default of 0?
- FLAGS_verbose = atoi(verbose_str);
- }
-
- bool need_heap_check = true;
- // The user indicates a desire for heap-checking via the HEAPCHECK
- // environment variable. If it's not set, there's no way to do
- // heap-checking.
- if (!GetenvBeforeMain("HEAPCHECK")) {
- need_heap_check = false;
- }
-#ifdef HAVE_GETEUID
- if (need_heap_check && getuid() != geteuid()) {
- // heap-checker writes out files. Thus, for security reasons, we don't
- // recognize the env. var. to turn on heap-checking if we're setuid.
- RAW_LOG(WARNING, ("HeapChecker: ignoring HEAPCHECK because "
- "program seems to be setuid\n"));
- need_heap_check = false;
- }
-#endif
- if (need_heap_check) {
- HeapLeakChecker::BeforeConstructorsLocked();
- }
-}
-
-// This function overrides the weak function defined in malloc_hook.cc and
-// called by one of the initial malloc hooks (malloc_hook.cc) when the very
-// first memory allocation or an mmap/sbrk happens. This ensures that
-// HeapLeakChecker is initialized and installs all its hooks early enough to
-// track absolutely all memory allocations and all memory region acquisitions
-// via mmap and sbrk.
-extern "C" void MallocHook_InitAtFirstAllocation_HeapLeakChecker() {
- HeapLeakChecker_BeforeConstructors();
-}
-
-// This function is executed after all global object destructors run.
-void HeapLeakChecker_AfterDestructors() {
- { SpinLockHolder l(&heap_checker_lock);
- // can get here (via forks?) with other pids
- if (heap_checker_pid != getpid()) return;
- }
- if (FLAGS_heap_check_after_destructors) {
- if (HeapLeakChecker::DoMainHeapCheck()) {
- const struct timespec sleep_time = { 0, 500000000 }; // 500 ms
- nanosleep(&sleep_time, NULL);
- // Need this hack to wait for other pthreads to exit.
- // Otherwise tcmalloc find errors
- // on a free() call from pthreads.
- }
- }
- SpinLockHolder l(&heap_checker_lock);
- RAW_CHECK(!do_main_heap_check, "should have done it");
-}
-
-//----------------------------------------------------------------------
-// HeapLeakChecker disabling helpers
-//----------------------------------------------------------------------
-
-// These functions are at the end of the file to prevent their inlining:
-
-// static
-void HeapLeakChecker::DisableChecksFromToLocked(const void* start_address,
- const void* end_address,
- int max_depth) {
- RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- RAW_DCHECK(start_address < end_address, "");
- if (disabled_ranges == NULL) {
- disabled_ranges = new(Allocator::Allocate(sizeof(DisabledRangeMap)))
- DisabledRangeMap;
- }
- RangeValue value;
- value.start_address = AsInt(start_address);
- value.max_depth = max_depth;
- if (disabled_ranges->insert(make_pair(AsInt(end_address), value)).second) {
- RAW_VLOG(10, "Disabling leak checking in stack traces "
- "under frame addresses between %p..%p",
- start_address, end_address);
- } else { // check that this is just a verbatim repetition
- RangeValue const& val = disabled_ranges->find(AsInt(end_address))->second;
- if (val.max_depth != value.max_depth ||
- val.start_address != value.start_address) {
- RAW_LOG(FATAL, "Two DisableChecksToHereFrom calls conflict: "
- "(%p, %p, %d) vs. (%p, %p, %d)",
- AsPtr(val.start_address), end_address, val.max_depth,
- start_address, end_address, max_depth);
- }
- }
-}
-
-// static
-inline bool HeapLeakChecker::HaveOnHeapLocked(const void** ptr,
- size_t* object_size) {
- // Commented-out because HaveOnHeapLocked is very performance-critical:
- // RAW_DCHECK(heap_checker_lock.IsHeld(), "");
- const uintptr_t addr = AsInt(*ptr);
- if (heap_profile->FindInsideAlloc(
- *ptr, max_heap_object_size, ptr, object_size)) {
- RAW_VLOG(16, "Got pointer into %p at +%" PRIuPTR " offset",
- *ptr, addr - AsInt(*ptr));
- return true;
- }
- return false;
-}
-
-// static
-const void* HeapLeakChecker::GetAllocCaller(void* ptr) {
- // this is used only in the unittest, so the heavy checks are fine
- HeapProfileTable::AllocInfo info;
- { SpinLockHolder l(&heap_checker_lock);
- RAW_CHECK(heap_profile->FindAllocDetails(ptr, &info), "");
- }
- RAW_CHECK(info.stack_depth >= 1, "");
- return info.call_stack[0];
-}
diff --git a/src/third_party/gperftools-2.5/src/heap-profile-stats.h b/src/third_party/gperftools-2.5/src/heap-profile-stats.h
deleted file mode 100644
index ae45d5883fa..00000000000
--- a/src/third_party/gperftools-2.5/src/heap-profile-stats.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2013, 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.
-
-// This file defines structs to accumulate memory allocation and deallocation
-// counts. These structs are commonly used for malloc (in HeapProfileTable)
-// and mmap (in MemoryRegionMap).
-
-// A bucket is data structure for heap profiling to store a pair of a stack
-// trace and counts of (de)allocation. Buckets are stored in a hash table
-// which is declared as "HeapProfileBucket**".
-//
-// A hash value is computed from a stack trace. Collision in the hash table
-// is resolved by separate chaining with linked lists. The links in the list
-// are implemented with the member "HeapProfileBucket* next".
-//
-// A structure of a hash table HeapProfileBucket** bucket_table would be like:
-// bucket_table[0] => NULL
-// bucket_table[1] => HeapProfileBucket() => HeapProfileBucket() => NULL
-// ...
-// bucket_table[i] => HeapProfileBucket() => NULL
-// ...
-// bucket_table[n] => HeapProfileBucket() => NULL
-
-#ifndef HEAP_PROFILE_STATS_H_
-#define HEAP_PROFILE_STATS_H_
-
-struct HeapProfileStats {
- // Returns true if the two HeapProfileStats are semantically equal.
- bool Equivalent(const HeapProfileStats& other) const {
- return allocs - frees == other.allocs - other.frees &&
- alloc_size - free_size == other.alloc_size - other.free_size;
- }
-
- int32 allocs; // Number of allocation calls.
- int32 frees; // Number of free calls.
- int64 alloc_size; // Total size of all allocated objects so far.
- int64 free_size; // Total size of all freed objects so far.
-};
-
-// Allocation and deallocation statistics per each stack trace.
-struct HeapProfileBucket : public HeapProfileStats {
- // Longest stack trace we record.
- static const int kMaxStackDepth = 32;
-
- uintptr_t hash; // Hash value of the stack trace.
- int depth; // Depth of stack trace.
- const void** stack; // Stack trace.
- HeapProfileBucket* next; // Next entry in hash-table.
-};
-
-#endif // HEAP_PROFILE_STATS_H_
diff --git a/src/third_party/gperftools-2.5/src/heap-profile-table.cc b/src/third_party/gperftools-2.5/src/heap-profile-table.cc
deleted file mode 100644
index 7486468c056..00000000000
--- a/src/third_party/gperftools-2.5/src/heap-profile-table.cc
+++ /dev/null
@@ -1,631 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2006, 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
-// Maxim Lifantsev (refactoring)
-//
-
-#include <config.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for write()
-#endif
-#include <fcntl.h> // for open()
-#ifdef HAVE_GLOB_H
-#include <glob.h>
-#ifndef GLOB_NOMATCH // true on some old cygwins
-# define GLOB_NOMATCH 0
-#endif
-#endif
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h> // for PRIxPTR
-#endif
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#endif
-#include <errno.h>
-#include <stdarg.h>
-#include <string>
-#include <map>
-#include <algorithm> // for sort(), equal(), and copy()
-
-#include "heap-profile-table.h"
-
-#include "base/logging.h"
-#include "raw_printer.h"
-#include "symbolize.h"
-#include <gperftools/stacktrace.h>
-#include <gperftools/malloc_hook.h>
-#include "memory_region_map.h"
-#include "base/commandlineflags.h"
-#include "base/logging.h" // for the RawFD I/O commands
-#include "base/sysinfo.h"
-
-using std::sort;
-using std::equal;
-using std::copy;
-using std::string;
-using std::map;
-
-using tcmalloc::FillProcSelfMaps; // from sysinfo.h
-using tcmalloc::DumpProcSelfMaps; // from sysinfo.h
-
-//----------------------------------------------------------------------
-
-DEFINE_bool(cleanup_old_heap_profiles,
- EnvToBool("HEAP_PROFILE_CLEANUP", true),
- "At initialization time, delete old heap profiles.");
-
-DEFINE_int32(heap_check_max_leaks,
- EnvToInt("HEAP_CHECK_MAX_LEAKS", 20),
- "The maximum number of leak reports to print.");
-
-//----------------------------------------------------------------------
-
-// header of the dumped heap profile
-static const char kProfileHeader[] = "heap profile: ";
-static const char kProcSelfMapsHeader[] = "\nMAPPED_LIBRARIES:\n";
-
-//----------------------------------------------------------------------
-
-const char HeapProfileTable::kFileExt[] = ".heap";
-
-//----------------------------------------------------------------------
-
-static const int kHashTableSize = 179999; // Size for bucket_table_.
-/*static*/ const int HeapProfileTable::kMaxStackDepth;
-
-//----------------------------------------------------------------------
-
-// We strip out different number of stack frames in debug mode
-// because less inlining happens in that case
-#ifdef NDEBUG
-static const int kStripFrames = 2;
-#else
-static const int kStripFrames = 3;
-#endif
-
-// For sorting Stats or Buckets by in-use space
-static bool ByAllocatedSpace(HeapProfileTable::Stats* a,
- HeapProfileTable::Stats* b) {
- // Return true iff "a" has more allocated space than "b"
- return (a->alloc_size - a->free_size) > (b->alloc_size - b->free_size);
-}
-
-//----------------------------------------------------------------------
-
-HeapProfileTable::HeapProfileTable(Allocator alloc,
- DeAllocator dealloc,
- bool profile_mmap)
- : alloc_(alloc),
- dealloc_(dealloc),
- profile_mmap_(profile_mmap),
- bucket_table_(NULL),
- num_buckets_(0),
- address_map_(NULL) {
- // Make a hash table for buckets.
- const int table_bytes = kHashTableSize * sizeof(*bucket_table_);
- bucket_table_ = static_cast<Bucket**>(alloc_(table_bytes));
- memset(bucket_table_, 0, table_bytes);
-
- // Make an allocation map.
- address_map_ =
- new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_);
-
- // Initialize.
- memset(&total_, 0, sizeof(total_));
- num_buckets_ = 0;
-}
-
-HeapProfileTable::~HeapProfileTable() {
- // Free the allocation map.
- address_map_->~AllocationMap();
- dealloc_(address_map_);
- address_map_ = NULL;
-
- // Free the hash table.
- for (int i = 0; i < kHashTableSize; i++) {
- for (Bucket* curr = bucket_table_[i]; curr != 0; /**/) {
- Bucket* bucket = curr;
- curr = curr->next;
- dealloc_(bucket->stack);
- dealloc_(bucket);
- }
- }
- dealloc_(bucket_table_);
- bucket_table_ = NULL;
-}
-
-HeapProfileTable::Bucket* HeapProfileTable::GetBucket(int depth,
- const void* const key[]) {
- // Make hash-value
- uintptr_t h = 0;
- for (int i = 0; i < depth; i++) {
- h += reinterpret_cast<uintptr_t>(key[i]);
- h += h << 10;
- h ^= h >> 6;
- }
- h += h << 3;
- h ^= h >> 11;
-
- // Lookup stack trace in table
- unsigned int buck = ((unsigned int) h) % kHashTableSize;
- for (Bucket* b = bucket_table_[buck]; b != 0; b = b->next) {
- if ((b->hash == h) &&
- (b->depth == depth) &&
- equal(key, key + depth, b->stack)) {
- return b;
- }
- }
-
- // Create new bucket
- const size_t key_size = sizeof(key[0]) * depth;
- const void** kcopy = reinterpret_cast<const void**>(alloc_(key_size));
- copy(key, key + depth, kcopy);
- Bucket* b = reinterpret_cast<Bucket*>(alloc_(sizeof(Bucket)));
- memset(b, 0, sizeof(*b));
- b->hash = h;
- b->depth = depth;
- b->stack = kcopy;
- b->next = bucket_table_[buck];
- bucket_table_[buck] = b;
- num_buckets_++;
- return b;
-}
-
-int HeapProfileTable::GetCallerStackTrace(
- int skip_count, void* stack[kMaxStackDepth]) {
- return MallocHook::GetCallerStackTrace(
- stack, kMaxStackDepth, kStripFrames + skip_count + 1);
-}
-
-void HeapProfileTable::RecordAlloc(
- const void* ptr, size_t bytes, int stack_depth,
- const void* const call_stack[]) {
- Bucket* b = GetBucket(stack_depth, call_stack);
- b->allocs++;
- b->alloc_size += bytes;
- total_.allocs++;
- total_.alloc_size += bytes;
-
- AllocValue v;
- v.set_bucket(b); // also did set_live(false); set_ignore(false)
- v.bytes = bytes;
- address_map_->Insert(ptr, v);
-}
-
-void HeapProfileTable::RecordFree(const void* ptr) {
- AllocValue v;
- if (address_map_->FindAndRemove(ptr, &v)) {
- Bucket* b = v.bucket();
- b->frees++;
- b->free_size += v.bytes;
- total_.frees++;
- total_.free_size += v.bytes;
- }
-}
-
-bool HeapProfileTable::FindAlloc(const void* ptr, size_t* object_size) const {
- const AllocValue* alloc_value = address_map_->Find(ptr);
- if (alloc_value != NULL) *object_size = alloc_value->bytes;
- return alloc_value != NULL;
-}
-
-bool HeapProfileTable::FindAllocDetails(const void* ptr,
- AllocInfo* info) const {
- const AllocValue* alloc_value = address_map_->Find(ptr);
- if (alloc_value != NULL) {
- info->object_size = alloc_value->bytes;
- info->call_stack = alloc_value->bucket()->stack;
- info->stack_depth = alloc_value->bucket()->depth;
- }
- return alloc_value != NULL;
-}
-
-bool HeapProfileTable::FindInsideAlloc(const void* ptr,
- size_t max_size,
- const void** object_ptr,
- size_t* object_size) const {
- const AllocValue* alloc_value =
- address_map_->FindInside(&AllocValueSize, max_size, ptr, object_ptr);
- if (alloc_value != NULL) *object_size = alloc_value->bytes;
- return alloc_value != NULL;
-}
-
-bool HeapProfileTable::MarkAsLive(const void* ptr) {
- AllocValue* alloc = address_map_->FindMutable(ptr);
- if (alloc && !alloc->live()) {
- alloc->set_live(true);
- return true;
- }
- return false;
-}
-
-void HeapProfileTable::MarkAsIgnored(const void* ptr) {
- AllocValue* alloc = address_map_->FindMutable(ptr);
- if (alloc) {
- alloc->set_ignore(true);
- }
-}
-
-// We'd be happier using snprintfer, but we don't to reduce dependencies.
-int HeapProfileTable::UnparseBucket(const Bucket& b,
- char* buf, int buflen, int bufsize,
- const char* extra,
- Stats* profile_stats) {
- if (profile_stats != NULL) {
- profile_stats->allocs += b.allocs;
- profile_stats->alloc_size += b.alloc_size;
- profile_stats->frees += b.frees;
- profile_stats->free_size += b.free_size;
- }
- int printed =
- snprintf(buf + buflen, bufsize - buflen, "%6d: %8" PRId64 " [%6d: %8" PRId64 "] @%s",
- b.allocs - b.frees,
- b.alloc_size - b.free_size,
- b.allocs,
- b.alloc_size,
- extra);
- // If it looks like the snprintf failed, ignore the fact we printed anything
- if (printed < 0 || printed >= bufsize - buflen) return buflen;
- buflen += printed;
- for (int d = 0; d < b.depth; d++) {
- printed = snprintf(buf + buflen, bufsize - buflen, " 0x%08" PRIxPTR,
- reinterpret_cast<uintptr_t>(b.stack[d]));
- if (printed < 0 || printed >= bufsize - buflen) return buflen;
- buflen += printed;
- }
- printed = snprintf(buf + buflen, bufsize - buflen, "\n");
- if (printed < 0 || printed >= bufsize - buflen) return buflen;
- buflen += printed;
- return buflen;
-}
-
-HeapProfileTable::Bucket**
-HeapProfileTable::MakeSortedBucketList() const {
- Bucket** list = static_cast<Bucket**>(alloc_(sizeof(Bucket) * num_buckets_));
-
- int bucket_count = 0;
- for (int i = 0; i < kHashTableSize; i++) {
- for (Bucket* curr = bucket_table_[i]; curr != 0; curr = curr->next) {
- list[bucket_count++] = curr;
- }
- }
- RAW_DCHECK(bucket_count == num_buckets_, "");
-
- sort(list, list + num_buckets_, ByAllocatedSpace);
-
- return list;
-}
-
-void HeapProfileTable::IterateOrderedAllocContexts(
- AllocContextIterator callback) const {
- Bucket** list = MakeSortedBucketList();
- AllocContextInfo info;
- for (int i = 0; i < num_buckets_; ++i) {
- *static_cast<Stats*>(&info) = *static_cast<Stats*>(list[i]);
- info.stack_depth = list[i]->depth;
- info.call_stack = list[i]->stack;
- callback(info);
- }
- dealloc_(list);
-}
-
-int HeapProfileTable::FillOrderedProfile(char buf[], int size) const {
- Bucket** list = MakeSortedBucketList();
-
- // Our file format is "bucket, bucket, ..., bucket, proc_self_maps_info".
- // In the cases buf is too small, we'd rather leave out the last
- // buckets than leave out the /proc/self/maps info. To ensure that,
- // we actually print the /proc/self/maps info first, then move it to
- // the end of the buffer, then write the bucket info into whatever
- // is remaining, and then move the maps info one last time to close
- // any gaps. Whew!
- int map_length = snprintf(buf, size, "%s", kProcSelfMapsHeader);
- if (map_length < 0 || map_length >= size) {
- dealloc_(list);
- return 0;
- }
- bool dummy; // "wrote_all" -- did /proc/self/maps fit in its entirety?
- map_length += FillProcSelfMaps(buf + map_length, size - map_length, &dummy);
- RAW_DCHECK(map_length <= size, "");
- char* const map_start = buf + size - map_length; // move to end
- memmove(map_start, buf, map_length);
- size -= map_length;
-
- Stats stats;
- memset(&stats, 0, sizeof(stats));
- int bucket_length = snprintf(buf, size, "%s", kProfileHeader);
- if (bucket_length < 0 || bucket_length >= size) {
- dealloc_(list);
- return 0;
- }
- bucket_length = UnparseBucket(total_, buf, bucket_length, size,
- " heapprofile", &stats);
-
- // Dump the mmap list first.
- if (profile_mmap_) {
- BufferArgs buffer(buf, bucket_length, size);
- MemoryRegionMap::IterateBuckets<BufferArgs*>(DumpBucketIterator, &buffer);
- bucket_length = buffer.buflen;
- }
-
- for (int i = 0; i < num_buckets_; i++) {
- bucket_length = UnparseBucket(*list[i], buf, bucket_length, size, "",
- &stats);
- }
- RAW_DCHECK(bucket_length < size, "");
-
- dealloc_(list);
-
- RAW_DCHECK(buf + bucket_length <= map_start, "");
- memmove(buf + bucket_length, map_start, map_length); // close the gap
-
- return bucket_length + map_length;
-}
-
-// static
-void HeapProfileTable::DumpBucketIterator(const Bucket* bucket,
- BufferArgs* args) {
- args->buflen = UnparseBucket(*bucket, args->buf, args->buflen, args->bufsize,
- "", NULL);
-}
-
-inline
-void HeapProfileTable::DumpNonLiveIterator(const void* ptr, AllocValue* v,
- const DumpArgs& args) {
- if (v->live()) {
- v->set_live(false);
- return;
- }
- if (v->ignore()) {
- return;
- }
- Bucket b;
- memset(&b, 0, sizeof(b));
- b.allocs = 1;
- b.alloc_size = v->bytes;
- b.depth = v->bucket()->depth;
- b.stack = v->bucket()->stack;
- char buf[1024];
- int len = UnparseBucket(b, buf, 0, sizeof(buf), "", args.profile_stats);
- RawWrite(args.fd, buf, len);
-}
-
-// Callback from NonLiveSnapshot; adds entry to arg->dest
-// if not the entry is not live and is not present in arg->base.
-void HeapProfileTable::AddIfNonLive(const void* ptr, AllocValue* v,
- AddNonLiveArgs* arg) {
- if (v->live()) {
- v->set_live(false);
- } else {
- if (arg->base != NULL && arg->base->map_.Find(ptr) != NULL) {
- // Present in arg->base, so do not save
- } else {
- arg->dest->Add(ptr, *v);
- }
- }
-}
-
-bool HeapProfileTable::WriteProfile(const char* file_name,
- const Bucket& total,
- AllocationMap* allocations) {
- RAW_VLOG(1, "Dumping non-live heap profile to %s", file_name);
- RawFD fd = RawOpenForWriting(file_name);
- if (fd != kIllegalRawFD) {
- RawWrite(fd, kProfileHeader, strlen(kProfileHeader));
- char buf[512];
- int len = UnparseBucket(total, buf, 0, sizeof(buf), " heapprofile",
- NULL);
- RawWrite(fd, buf, len);
- const DumpArgs args(fd, NULL);
- allocations->Iterate<const DumpArgs&>(DumpNonLiveIterator, args);
- RawWrite(fd, kProcSelfMapsHeader, strlen(kProcSelfMapsHeader));
- DumpProcSelfMaps(fd);
- RawClose(fd);
- return true;
- } else {
- RAW_LOG(ERROR, "Failed dumping filtered heap profile to %s", file_name);
- return false;
- }
-}
-
-void HeapProfileTable::CleanupOldProfiles(const char* prefix) {
- if (!FLAGS_cleanup_old_heap_profiles)
- return;
- string pattern = string(prefix) + ".*" + kFileExt;
-#if defined(HAVE_GLOB_H)
- glob_t g;
- const int r = glob(pattern.c_str(), GLOB_ERR, NULL, &g);
- if (r == 0 || r == GLOB_NOMATCH) {
- const int prefix_length = strlen(prefix);
- for (int i = 0; i < g.gl_pathc; i++) {
- const char* fname = g.gl_pathv[i];
- if ((strlen(fname) >= prefix_length) &&
- (memcmp(fname, prefix, prefix_length) == 0)) {
- RAW_VLOG(1, "Removing old heap profile %s", fname);
- unlink(fname);
- }
- }
- }
- globfree(&g);
-#else /* HAVE_GLOB_H */
- RAW_LOG(WARNING, "Unable to remove old heap profiles (can't run glob())");
-#endif
-}
-
-HeapProfileTable::Snapshot* HeapProfileTable::TakeSnapshot() {
- Snapshot* s = new (alloc_(sizeof(Snapshot))) Snapshot(alloc_, dealloc_);
- address_map_->Iterate(AddToSnapshot, s);
- return s;
-}
-
-void HeapProfileTable::ReleaseSnapshot(Snapshot* s) {
- s->~Snapshot();
- dealloc_(s);
-}
-
-// Callback from TakeSnapshot; adds a single entry to snapshot
-void HeapProfileTable::AddToSnapshot(const void* ptr, AllocValue* v,
- Snapshot* snapshot) {
- snapshot->Add(ptr, *v);
-}
-
-HeapProfileTable::Snapshot* HeapProfileTable::NonLiveSnapshot(
- Snapshot* base) {
- RAW_VLOG(2, "NonLiveSnapshot input: %d %d\n",
- int(total_.allocs - total_.frees),
- int(total_.alloc_size - total_.free_size));
-
- Snapshot* s = new (alloc_(sizeof(Snapshot))) Snapshot(alloc_, dealloc_);
- AddNonLiveArgs args;
- args.dest = s;
- args.base = base;
- address_map_->Iterate<AddNonLiveArgs*>(AddIfNonLive, &args);
- RAW_VLOG(2, "NonLiveSnapshot output: %d %d\n",
- int(s->total_.allocs - s->total_.frees),
- int(s->total_.alloc_size - s->total_.free_size));
- return s;
-}
-
-// Information kept per unique bucket seen
-struct HeapProfileTable::Snapshot::Entry {
- int count;
- int bytes;
- Bucket* bucket;
- Entry() : count(0), bytes(0) { }
-
- // Order by decreasing bytes
- bool operator<(const Entry& x) const {
- return this->bytes > x.bytes;
- }
-};
-
-// State used to generate leak report. We keep a mapping from Bucket pointer
-// the collected stats for that bucket.
-struct HeapProfileTable::Snapshot::ReportState {
- map<Bucket*, Entry> buckets_;
-};
-
-// Callback from ReportLeaks; updates ReportState.
-void HeapProfileTable::Snapshot::ReportCallback(const void* ptr,
- AllocValue* v,
- ReportState* state) {
- Entry* e = &state->buckets_[v->bucket()]; // Creates empty Entry first time
- e->bucket = v->bucket();
- e->count++;
- e->bytes += v->bytes;
-}
-
-void HeapProfileTable::Snapshot::ReportLeaks(const char* checker_name,
- const char* filename,
- bool should_symbolize) {
- // This is only used by the heap leak checker, but is intimately
- // tied to the allocation map that belongs in this module and is
- // therefore placed here.
- RAW_LOG(ERROR, "Leak check %s detected leaks of %" PRIuS " bytes "
- "in %" PRIuS " objects",
- checker_name,
- size_t(total_.alloc_size),
- size_t(total_.allocs));
-
- // Group objects by Bucket
- ReportState state;
- map_.Iterate(&ReportCallback, &state);
-
- // Sort buckets by decreasing leaked size
- const int n = state.buckets_.size();
- Entry* entries = new Entry[n];
- int dst = 0;
- for (map<Bucket*,Entry>::const_iterator iter = state.buckets_.begin();
- iter != state.buckets_.end();
- ++iter) {
- entries[dst++] = iter->second;
- }
- sort(entries, entries + n);
-
- // Report a bounded number of leaks to keep the leak report from
- // growing too long.
- const int to_report =
- (FLAGS_heap_check_max_leaks > 0 &&
- n > FLAGS_heap_check_max_leaks) ? FLAGS_heap_check_max_leaks : n;
- RAW_LOG(ERROR, "The %d largest leaks:", to_report);
-
- // Print
- SymbolTable symbolization_table;
- for (int i = 0; i < to_report; i++) {
- const Entry& e = entries[i];
- for (int j = 0; j < e.bucket->depth; j++) {
- symbolization_table.Add(e.bucket->stack[j]);
- }
- }
- static const int kBufSize = 2<<10;
- char buffer[kBufSize];
- if (should_symbolize)
- symbolization_table.Symbolize();
- for (int i = 0; i < to_report; i++) {
- const Entry& e = entries[i];
- base::RawPrinter printer(buffer, kBufSize);
- printer.Printf("Leak of %d bytes in %d objects allocated from:\n",
- e.bytes, e.count);
- for (int j = 0; j < e.bucket->depth; j++) {
- const void* pc = e.bucket->stack[j];
- printer.Printf("\t@ %" PRIxPTR " %s\n",
- reinterpret_cast<uintptr_t>(pc), symbolization_table.GetSymbol(pc));
- }
- RAW_LOG(ERROR, "%s", buffer);
- }
-
- if (to_report < n) {
- RAW_LOG(ERROR, "Skipping leaks numbered %d..%d",
- to_report, n-1);
- }
- delete[] entries;
-
- // TODO: Dump the sorted Entry list instead of dumping raw data?
- // (should be much shorter)
- if (!HeapProfileTable::WriteProfile(filename, total_, &map_)) {
- RAW_LOG(ERROR, "Could not write pprof profile to %s", filename);
- }
-}
-
-void HeapProfileTable::Snapshot::ReportObject(const void* ptr,
- AllocValue* v,
- char* unused) {
- // Perhaps also log the allocation stack trace (unsymbolized)
- // on this line in case somebody finds it useful.
- RAW_LOG(ERROR, "leaked %" PRIuS " byte object %p", v->bytes, ptr);
-}
-
-void HeapProfileTable::Snapshot::ReportIndividualObjects() {
- char unused;
- map_.Iterate(ReportObject, &unused);
-}
diff --git a/src/third_party/gperftools-2.5/src/heap-profile-table.h b/src/third_party/gperftools-2.5/src/heap-profile-table.h
deleted file mode 100644
index 3c6284741af..00000000000
--- a/src/third_party/gperftools-2.5/src/heap-profile-table.h
+++ /dev/null
@@ -1,399 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2006, 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
-// Maxim Lifantsev (refactoring)
-//
-
-#ifndef BASE_HEAP_PROFILE_TABLE_H_
-#define BASE_HEAP_PROFILE_TABLE_H_
-
-#include "addressmap-inl.h"
-#include "base/basictypes.h"
-#include "base/logging.h" // for RawFD
-#include "heap-profile-stats.h"
-
-// Table to maintain a heap profile data inside,
-// i.e. the set of currently active heap memory allocations.
-// thread-unsafe and non-reentrant code:
-// each instance object must be used by one thread
-// at a time w/o self-recursion.
-//
-// TODO(maxim): add a unittest for this class.
-class HeapProfileTable {
- public:
-
- // Extension to be used for heap pforile files.
- static const char kFileExt[];
-
- // Longest stack trace we record.
- static const int kMaxStackDepth = 32;
-
- // data types ----------------------------
-
- // Profile stats.
- typedef HeapProfileStats Stats;
-
- // Info we can return about an allocation.
- struct AllocInfo {
- size_t object_size; // size of the allocation
- const void* const* call_stack; // call stack that made the allocation call
- int stack_depth; // depth of call_stack
- bool live;
- bool ignored;
- };
-
- // Info we return about an allocation context.
- // An allocation context is a unique caller stack trace
- // of an allocation operation.
- struct AllocContextInfo : public Stats {
- int stack_depth; // Depth of stack trace
- const void* const* call_stack; // Stack trace
- };
-
- // Memory (de)allocator interface we'll use.
- typedef void* (*Allocator)(size_t size);
- typedef void (*DeAllocator)(void* ptr);
-
- // interface ---------------------------
-
- HeapProfileTable(Allocator alloc, DeAllocator dealloc, bool profile_mmap);
- ~HeapProfileTable();
-
- // Collect the stack trace for the function that asked to do the
- // allocation for passing to RecordAlloc() below.
- //
- // The stack trace is stored in 'stack'. The stack depth is returned.
- //
- // 'skip_count' gives the number of stack frames between this call
- // and the memory allocation function.
- static int GetCallerStackTrace(int skip_count, void* stack[kMaxStackDepth]);
-
- // Record an allocation at 'ptr' of 'bytes' bytes. 'stack_depth'
- // and 'call_stack' identifying the function that requested the
- // allocation. They can be generated using GetCallerStackTrace() above.
- void RecordAlloc(const void* ptr, size_t bytes,
- int stack_depth, const void* const call_stack[]);
-
- // Record the deallocation of memory at 'ptr'.
- void RecordFree(const void* ptr);
-
- // Return true iff we have recorded an allocation at 'ptr'.
- // If yes, fill *object_size with the allocation byte size.
- bool FindAlloc(const void* ptr, size_t* object_size) const;
- // Same as FindAlloc, but fills all of *info.
- bool FindAllocDetails(const void* ptr, AllocInfo* info) const;
-
- // Return true iff "ptr" points into a recorded allocation
- // If yes, fill *object_ptr with the actual allocation address
- // and *object_size with the allocation byte size.
- // max_size specifies largest currently possible allocation size.
- bool FindInsideAlloc(const void* ptr, size_t max_size,
- const void** object_ptr, size_t* object_size) const;
-
- // If "ptr" points to a recorded allocation and it's not marked as live
- // mark it as live and return true. Else return false.
- // All allocations start as non-live.
- bool MarkAsLive(const void* ptr);
-
- // If "ptr" points to a recorded allocation, mark it as "ignored".
- // Ignored objects are treated like other objects, except that they
- // are skipped in heap checking reports.
- void MarkAsIgnored(const void* ptr);
-
- // Return current total (de)allocation statistics. It doesn't contain
- // mmap'ed regions.
- const Stats& total() const { return total_; }
-
- // Allocation data iteration callback: gets passed object pointer and
- // fully-filled AllocInfo.
- typedef void (*AllocIterator)(const void* ptr, const AllocInfo& info);
-
- // Iterate over the allocation profile data calling "callback"
- // for every allocation.
- void IterateAllocs(AllocIterator callback) const {
- address_map_->Iterate(MapArgsAllocIterator, callback);
- }
-
- // Allocation context profile data iteration callback
- typedef void (*AllocContextIterator)(const AllocContextInfo& info);
-
- // Iterate over the allocation context profile data calling "callback"
- // for every allocation context. Allocation contexts are ordered by the
- // size of allocated space.
- void IterateOrderedAllocContexts(AllocContextIterator callback) const;
-
- // Fill profile data into buffer 'buf' of size 'size'
- // and return the actual size occupied by the dump in 'buf'.
- // The profile buckets are dumped in the decreasing order
- // of currently allocated bytes.
- // We do not provision for 0-terminating 'buf'.
- int FillOrderedProfile(char buf[], int size) const;
-
- // Cleanup any old profile files matching prefix + ".*" + kFileExt.
- static void CleanupOldProfiles(const char* prefix);
-
- // Return a snapshot of the current contents of *this.
- // Caller must call ReleaseSnapshot() on result when no longer needed.
- // The result is only valid while this exists and until
- // the snapshot is discarded by calling ReleaseSnapshot().
- class Snapshot;
- Snapshot* TakeSnapshot();
-
- // Release a previously taken snapshot. snapshot must not
- // be used after this call.
- void ReleaseSnapshot(Snapshot* snapshot);
-
- // Return a snapshot of every non-live, non-ignored object in *this.
- // If "base" is non-NULL, skip any objects present in "base".
- // As a side-effect, clears the "live" bit on every live object in *this.
- // Caller must call ReleaseSnapshot() on result when no longer needed.
- Snapshot* NonLiveSnapshot(Snapshot* base);
-
- private:
-
- // data types ----------------------------
-
- // Hash table bucket to hold (de)allocation stats
- // for a given allocation call stack trace.
- typedef HeapProfileBucket Bucket;
-
- // Info stored in the address map
- struct AllocValue {
- // Access to the stack-trace bucket
- Bucket* bucket() const {
- return reinterpret_cast<Bucket*>(bucket_rep & ~uintptr_t(kMask));
- }
- // This also does set_live(false).
- void set_bucket(Bucket* b) { bucket_rep = reinterpret_cast<uintptr_t>(b); }
- size_t bytes; // Number of bytes in this allocation
-
- // Access to the allocation liveness flag (for leak checking)
- bool live() const { return bucket_rep & kLive; }
- void set_live(bool l) {
- bucket_rep = (bucket_rep & ~uintptr_t(kLive)) | (l ? kLive : 0);
- }
-
- // Should this allocation be ignored if it looks like a leak?
- bool ignore() const { return bucket_rep & kIgnore; }
- void set_ignore(bool r) {
- bucket_rep = (bucket_rep & ~uintptr_t(kIgnore)) | (r ? kIgnore : 0);
- }
-
- private:
- // We store a few bits in the bottom bits of bucket_rep.
- // (Alignment is at least four, so we have at least two bits.)
- static const int kLive = 1;
- static const int kIgnore = 2;
- static const int kMask = kLive | kIgnore;
-
- uintptr_t bucket_rep;
- };
-
- // helper for FindInsideAlloc
- static size_t AllocValueSize(const AllocValue& v) { return v.bytes; }
-
- typedef AddressMap<AllocValue> AllocationMap;
-
- // Arguments that need to be passed DumpBucketIterator callback below.
- struct BufferArgs {
- BufferArgs(char* buf_arg, int buflen_arg, int bufsize_arg)
- : buf(buf_arg),
- buflen(buflen_arg),
- bufsize(bufsize_arg) {
- }
-
- char* buf;
- int buflen;
- int bufsize;
-
- DISALLOW_COPY_AND_ASSIGN(BufferArgs);
- };
-
- // Arguments that need to be passed DumpNonLiveIterator callback below.
- struct DumpArgs {
- DumpArgs(RawFD fd_arg, Stats* profile_stats_arg)
- : fd(fd_arg),
- profile_stats(profile_stats_arg) {
- }
-
- RawFD fd; // file to write to
- Stats* profile_stats; // stats to update (may be NULL)
- };
-
- // helpers ----------------------------
-
- // Unparse bucket b and print its portion of profile dump into buf.
- // We return the amount of space in buf that we use. We start printing
- // at buf + buflen, and promise not to go beyond buf + bufsize.
- // We do not provision for 0-terminating 'buf'.
- //
- // If profile_stats is non-NULL, we update *profile_stats by
- // counting bucket b.
- //
- // "extra" is appended to the unparsed bucket. Typically it is empty,
- // but may be set to something like " heapprofile" for the total
- // bucket to indicate the type of the profile.
- static int UnparseBucket(const Bucket& b,
- char* buf, int buflen, int bufsize,
- const char* extra,
- Stats* profile_stats);
-
- // Get the bucket for the caller stack trace 'key' of depth 'depth'
- // creating the bucket if needed.
- Bucket* GetBucket(int depth, const void* const key[]);
-
- // Helper for IterateAllocs to do callback signature conversion
- // from AllocationMap::Iterate to AllocIterator.
- static void MapArgsAllocIterator(const void* ptr, AllocValue* v,
- AllocIterator callback) {
- AllocInfo info;
- info.object_size = v->bytes;
- info.call_stack = v->bucket()->stack;
- info.stack_depth = v->bucket()->depth;
- info.live = v->live();
- info.ignored = v->ignore();
- callback(ptr, info);
- }
-
- // Helper to dump a bucket.
- inline static void DumpBucketIterator(const Bucket* bucket,
- BufferArgs* args);
-
- // Helper for DumpNonLiveProfile to do object-granularity
- // heap profile dumping. It gets passed to AllocationMap::Iterate.
- inline static void DumpNonLiveIterator(const void* ptr, AllocValue* v,
- const DumpArgs& args);
-
- // Helper for IterateOrderedAllocContexts and FillOrderedProfile.
- // Creates a sorted list of Buckets whose length is num_buckets_.
- // The caller is responsible for deallocating the returned list.
- Bucket** MakeSortedBucketList() const;
-
- // Helper for TakeSnapshot. Saves object to snapshot.
- static void AddToSnapshot(const void* ptr, AllocValue* v, Snapshot* s);
-
- // Arguments passed to AddIfNonLive
- struct AddNonLiveArgs {
- Snapshot* dest;
- Snapshot* base;
- };
-
- // Helper for NonLiveSnapshot. Adds the object to the destination
- // snapshot if it is non-live.
- static void AddIfNonLive(const void* ptr, AllocValue* v,
- AddNonLiveArgs* arg);
-
- // Write contents of "*allocations" as a heap profile to
- // "file_name". "total" must contain the total of all entries in
- // "*allocations".
- static bool WriteProfile(const char* file_name,
- const Bucket& total,
- AllocationMap* allocations);
-
- // data ----------------------------
-
- // Memory (de)allocator that we use.
- Allocator alloc_;
- DeAllocator dealloc_;
-
- // Overall profile stats; we use only the Stats part,
- // but make it a Bucket to pass to UnparseBucket.
- Bucket total_;
-
- bool profile_mmap_;
-
- // Bucket hash table for malloc.
- // We hand-craft one instead of using one of the pre-written
- // ones because we do not want to use malloc when operating on the table.
- // It is only few lines of code, so no big deal.
- Bucket** bucket_table_;
- int num_buckets_;
-
- // Map of all currently allocated objects and mapped regions we know about.
- AllocationMap* address_map_;
-
- DISALLOW_COPY_AND_ASSIGN(HeapProfileTable);
-};
-
-class HeapProfileTable::Snapshot {
- public:
- const Stats& total() const { return total_; }
-
- // Report anything in this snapshot as a leak.
- // May use new/delete for temporary storage.
- // If should_symbolize is true, will fork (which is not threadsafe)
- // to turn addresses into symbol names. Set to false for maximum safety.
- // Also writes a heap profile to "filename" that contains
- // all of the objects in this snapshot.
- void ReportLeaks(const char* checker_name, const char* filename,
- bool should_symbolize);
-
- // Report the addresses of all leaked objects.
- // May use new/delete for temporary storage.
- void ReportIndividualObjects();
-
- bool Empty() const {
- return (total_.allocs == 0) && (total_.alloc_size == 0);
- }
-
- private:
- friend class HeapProfileTable;
-
- // Total count/size are stored in a Bucket so we can reuse UnparseBucket
- Bucket total_;
-
- // We share the Buckets managed by the parent table, but have our
- // own object->bucket map.
- AllocationMap map_;
-
- Snapshot(Allocator alloc, DeAllocator dealloc) : map_(alloc, dealloc) {
- memset(&total_, 0, sizeof(total_));
- }
-
- // Callback used to populate a Snapshot object with entries found
- // in another allocation map.
- inline void Add(const void* ptr, const AllocValue& v) {
- map_.Insert(ptr, v);
- total_.allocs++;
- total_.alloc_size += v.bytes;
- }
-
- // Helpers for sorting and generating leak reports
- struct Entry;
- struct ReportState;
- static void ReportCallback(const void* ptr, AllocValue* v, ReportState*);
- static void ReportObject(const void* ptr, AllocValue* v, char*);
-
- DISALLOW_COPY_AND_ASSIGN(Snapshot);
-};
-
-#endif // BASE_HEAP_PROFILE_TABLE_H_
diff --git a/src/third_party/gperftools-2.5/src/heap-profiler.cc b/src/third_party/gperftools-2.5/src/heap-profiler.cc
deleted file mode 100755
index 17d86976bc4..00000000000
--- a/src/third_party/gperftools-2.5/src/heap-profiler.cc
+++ /dev/null
@@ -1,620 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-//
-// TODO: Log large allocations
-
-#include <config.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h> // for open()
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-#include <errno.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <signal.h>
-
-#include <algorithm>
-#include <string>
-
-#include <gperftools/heap-profiler.h>
-
-#include "base/logging.h"
-#include "base/basictypes.h" // for PRId64, among other things
-#include "base/googleinit.h"
-#include "base/commandlineflags.h"
-#include "malloc_hook-inl.h"
-#include "tcmalloc_guard.h"
-#include <gperftools/malloc_hook.h>
-#include <gperftools/malloc_extension.h>
-#include "base/spinlock.h"
-#include "base/low_level_alloc.h"
-#include "base/sysinfo.h" // for GetUniquePathFromEnv()
-#include "heap-profile-table.h"
-#include "memory_region_map.h"
-
-
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 4096 // seems conservative for max filename len!
-#endif
-#endif
-
-using STL_NAMESPACE::string;
-using STL_NAMESPACE::sort;
-
-//----------------------------------------------------------------------
-// Flags that control heap-profiling
-//
-// The thread-safety of the profiler depends on these being immutable
-// after main starts, so don't change them.
-//----------------------------------------------------------------------
-
-DEFINE_int64(heap_profile_allocation_interval,
- EnvToInt64("HEAP_PROFILE_ALLOCATION_INTERVAL", 1 << 30 /*1GB*/),
- "If non-zero, dump heap profiling information once every "
- "specified number of bytes allocated by the program since "
- "the last dump.");
-DEFINE_int64(heap_profile_deallocation_interval,
- EnvToInt64("HEAP_PROFILE_DEALLOCATION_INTERVAL", 0),
- "If non-zero, dump heap profiling information once every "
- "specified number of bytes deallocated by the program "
- "since the last dump.");
-// We could also add flags that report whenever inuse_bytes changes by
-// X or -X, but there hasn't been a need for that yet, so we haven't.
-DEFINE_int64(heap_profile_inuse_interval,
- EnvToInt64("HEAP_PROFILE_INUSE_INTERVAL", 100 << 20 /*100MB*/),
- "If non-zero, dump heap profiling information whenever "
- "the high-water memory usage mark increases by the specified "
- "number of bytes.");
-DEFINE_int64(heap_profile_time_interval,
- EnvToInt64("HEAP_PROFILE_TIME_INTERVAL", 0),
- "If non-zero, dump heap profiling information once every "
- "specified number of seconds since the last dump.");
-DEFINE_bool(mmap_log,
- EnvToBool("HEAP_PROFILE_MMAP_LOG", false),
- "Should mmap/munmap calls be logged?");
-DEFINE_bool(mmap_profile,
- EnvToBool("HEAP_PROFILE_MMAP", false),
- "If heap-profiling is on, also profile mmap, mremap, and sbrk)");
-DEFINE_bool(only_mmap_profile,
- EnvToBool("HEAP_PROFILE_ONLY_MMAP", false),
- "If heap-profiling is on, only profile mmap, mremap, and sbrk; "
- "do not profile malloc/new/etc");
-
-
-//----------------------------------------------------------------------
-// Locking
-//----------------------------------------------------------------------
-
-// A pthread_mutex has way too much lock contention to be used here.
-//
-// I would like to use Mutex, but it can call malloc(),
-// which can cause us to fall into an infinite recursion.
-//
-// So we use a simple spinlock.
-static SpinLock heap_lock(SpinLock::LINKER_INITIALIZED);
-
-//----------------------------------------------------------------------
-// Simple allocator for heap profiler's internal memory
-//----------------------------------------------------------------------
-
-static LowLevelAlloc::Arena *heap_profiler_memory;
-
-static void* ProfilerMalloc(size_t bytes) {
- return LowLevelAlloc::AllocWithArena(bytes, heap_profiler_memory);
-}
-static void ProfilerFree(void* p) {
- LowLevelAlloc::Free(p);
-}
-
-// We use buffers of this size in DoGetHeapProfile.
-static const int kProfileBufferSize = 1 << 20;
-
-// This is a last-ditch buffer we use in DumpProfileLocked in case we
-// can't allocate more memory from ProfilerMalloc. We expect this
-// will be used by HeapProfileEndWriter when the application has to
-// exit due to out-of-memory. This buffer is allocated in
-// HeapProfilerStart. Access to this must be protected by heap_lock.
-static char* global_profiler_buffer = NULL;
-
-
-//----------------------------------------------------------------------
-// Profiling control/state data
-//----------------------------------------------------------------------
-
-// Access to all of these is protected by heap_lock.
-static bool is_on = false; // If are on as a subsytem.
-static bool dumping = false; // Dumping status to prevent recursion
-static char* filename_prefix = NULL; // Prefix used for profile file names
- // (NULL if no need for dumping yet)
-static int dump_count = 0; // How many dumps so far
-static int64 last_dump_alloc = 0; // alloc_size when did we last dump
-static int64 last_dump_free = 0; // free_size when did we last dump
-static int64 high_water_mark = 0; // In-use-bytes at last high-water dump
-static int64 last_dump_time = 0; // The time of the last dump
-
-static HeapProfileTable* heap_profile = NULL; // the heap profile table
-
-//----------------------------------------------------------------------
-// Profile generation
-//----------------------------------------------------------------------
-
-// Input must be a buffer of size at least 1MB.
-static char* DoGetHeapProfileLocked(char* buf, int buflen) {
- // We used to be smarter about estimating the required memory and
- // then capping it to 1MB and generating the profile into that.
- if (buf == NULL || buflen < 1)
- return NULL;
-
- RAW_DCHECK(heap_lock.IsHeld(), "");
- int bytes_written = 0;
- if (is_on) {
- HeapProfileTable::Stats const stats = heap_profile->total();
- (void)stats; // avoid an unused-variable warning in non-debug mode.
- bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1);
- // FillOrderedProfile should not reduce the set of active mmap-ed regions,
- // hence MemoryRegionMap will let us remove everything we've added above:
- RAW_DCHECK(stats.Equivalent(heap_profile->total()), "");
- // if this fails, we somehow removed by FillOrderedProfile
- // more than we have added.
- }
- buf[bytes_written] = '\0';
- RAW_DCHECK(bytes_written == strlen(buf), "");
-
- return buf;
-}
-
-extern "C" char* GetHeapProfile() {
- // Use normal malloc: we return the profile to the user to free it:
- char* buffer = reinterpret_cast<char*>(malloc(kProfileBufferSize));
- SpinLockHolder l(&heap_lock);
- return DoGetHeapProfileLocked(buffer, kProfileBufferSize);
-}
-
-// defined below
-static void NewHook(const void* ptr, size_t size);
-static void DeleteHook(const void* ptr);
-
-// Helper for HeapProfilerDump.
-static void DumpProfileLocked(const char* reason) {
- RAW_DCHECK(heap_lock.IsHeld(), "");
- RAW_DCHECK(is_on, "");
- RAW_DCHECK(!dumping, "");
-
- if (filename_prefix == NULL) return; // we do not yet need dumping
-
- dumping = true;
-
- // Make file name
- char file_name[1000];
- dump_count++;
- snprintf(file_name, sizeof(file_name), "%s.%04d%s",
- filename_prefix, dump_count, HeapProfileTable::kFileExt);
-
- // Dump the profile
- RAW_VLOG(0, "Dumping heap profile to %s (%s)", file_name, reason);
- // We must use file routines that don't access memory, since we hold
- // a memory lock now.
- RawFD fd = RawOpenForWriting(file_name);
- if (fd == kIllegalRawFD) {
- RAW_LOG(ERROR, "Failed dumping heap profile to %s", file_name);
- dumping = false;
- return;
- }
-
- // This case may be impossible, but it's best to be safe.
- // It's safe to use the global buffer: we're protected by heap_lock.
- if (global_profiler_buffer == NULL) {
- global_profiler_buffer =
- reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize));
- }
-
- char* profile = DoGetHeapProfileLocked(global_profiler_buffer,
- kProfileBufferSize);
- RawWrite(fd, profile, strlen(profile));
- RawClose(fd);
-
- dumping = false;
-}
-
-//----------------------------------------------------------------------
-// Profile collection
-//----------------------------------------------------------------------
-
-// Dump a profile after either an allocation or deallocation, if
-// the memory use has changed enough since the last dump.
-static void MaybeDumpProfileLocked() {
- if (!dumping) {
- const HeapProfileTable::Stats& total = heap_profile->total();
- const int64 inuse_bytes = total.alloc_size - total.free_size;
- bool need_to_dump = false;
- char buf[128];
- int64 current_time = time(NULL);
- if (FLAGS_heap_profile_allocation_interval > 0 &&
- total.alloc_size >=
- last_dump_alloc + FLAGS_heap_profile_allocation_interval) {
- snprintf(buf, sizeof(buf), ("%" PRId64 " MB allocated cumulatively, "
- "%" PRId64 " MB currently in use"),
- total.alloc_size >> 20, inuse_bytes >> 20);
- need_to_dump = true;
- } else if (FLAGS_heap_profile_deallocation_interval > 0 &&
- total.free_size >=
- last_dump_free + FLAGS_heap_profile_deallocation_interval) {
- snprintf(buf, sizeof(buf), ("%" PRId64 " MB freed cumulatively, "
- "%" PRId64 " MB currently in use"),
- total.free_size >> 20, inuse_bytes >> 20);
- need_to_dump = true;
- } else if (FLAGS_heap_profile_inuse_interval > 0 &&
- inuse_bytes >
- high_water_mark + FLAGS_heap_profile_inuse_interval) {
- snprintf(buf, sizeof(buf), "%" PRId64 " MB currently in use",
- inuse_bytes >> 20);
- need_to_dump = true;
- } else if (FLAGS_heap_profile_time_interval > 0 &&
- current_time - last_dump_time >=
- FLAGS_heap_profile_time_interval) {
- snprintf(buf, sizeof(buf), "%" PRId64 " sec since the last dump",
- current_time - last_dump_time);
- need_to_dump = true;
- last_dump_time = current_time;
- }
- if (need_to_dump) {
- DumpProfileLocked(buf);
-
- last_dump_alloc = total.alloc_size;
- last_dump_free = total.free_size;
- if (inuse_bytes > high_water_mark)
- high_water_mark = inuse_bytes;
- }
- }
-}
-
-// Record an allocation in the profile.
-static void RecordAlloc(const void* ptr, size_t bytes, int skip_count) {
- // Take the stack trace outside the critical section.
- void* stack[HeapProfileTable::kMaxStackDepth];
- int depth = HeapProfileTable::GetCallerStackTrace(skip_count + 1, stack);
- SpinLockHolder l(&heap_lock);
- if (is_on) {
- heap_profile->RecordAlloc(ptr, bytes, depth, stack);
- MaybeDumpProfileLocked();
- }
-}
-
-// Record a deallocation in the profile.
-static void RecordFree(const void* ptr) {
- SpinLockHolder l(&heap_lock);
- if (is_on) {
- heap_profile->RecordFree(ptr);
- MaybeDumpProfileLocked();
- }
-}
-
-//----------------------------------------------------------------------
-// Allocation/deallocation hooks for MallocHook
-//----------------------------------------------------------------------
-
-// static
-void NewHook(const void* ptr, size_t size) {
- if (ptr != NULL) RecordAlloc(ptr, size, 0);
-}
-
-// static
-void DeleteHook(const void* ptr) {
- if (ptr != NULL) RecordFree(ptr);
-}
-
-// TODO(jandrews): Re-enable stack tracing
-#ifdef TODO_REENABLE_STACK_TRACING
-static void RawInfoStackDumper(const char* message, void*) {
- RAW_LOG(INFO, "%.*s", static_cast<int>(strlen(message) - 1), message);
- // -1 is to chop the \n which will be added by RAW_LOG
-}
-#endif
-
-static void MmapHook(const void* result, const void* start, size_t size,
- int prot, int flags, int fd, off_t offset) {
- if (FLAGS_mmap_log) { // log it
- // We use PRIxS not just '%p' to avoid deadlocks
- // in pretty-printing of NULL as "nil".
- // TODO(maxim): instead should use a safe snprintf reimplementation
- RAW_LOG(INFO,
- "mmap(start=0x%" PRIxPTR ", len=%" PRIuS ", prot=0x%x, flags=0x%x, "
- "fd=%d, offset=0x%x) = 0x%" PRIxPTR "",
- (uintptr_t) start, size, prot, flags, fd, (unsigned int) offset,
- (uintptr_t) result);
-#ifdef TODO_REENABLE_STACK_TRACING
- DumpStackTrace(1, RawInfoStackDumper, NULL);
-#endif
- }
-}
-
-static void MremapHook(const void* result, const void* old_addr,
- size_t old_size, size_t new_size,
- int flags, const void* new_addr) {
- if (FLAGS_mmap_log) { // log it
- // We use PRIxS not just '%p' to avoid deadlocks
- // in pretty-printing of NULL as "nil".
- // TODO(maxim): instead should use a safe snprintf reimplementation
- RAW_LOG(INFO,
- "mremap(old_addr=0x%" PRIxPTR ", old_size=%" PRIuS ", "
- "new_size=%" PRIuS ", flags=0x%x, new_addr=0x%" PRIxPTR ") = "
- "0x%" PRIxPTR "",
- (uintptr_t) old_addr, old_size, new_size, flags,
- (uintptr_t) new_addr, (uintptr_t) result);
-#ifdef TODO_REENABLE_STACK_TRACING
- DumpStackTrace(1, RawInfoStackDumper, NULL);
-#endif
- }
-}
-
-static void MunmapHook(const void* ptr, size_t size) {
- if (FLAGS_mmap_log) { // log it
- // We use PRIxS not just '%p' to avoid deadlocks
- // in pretty-printing of NULL as "nil".
- // TODO(maxim): instead should use a safe snprintf reimplementation
- RAW_LOG(INFO, "munmap(start=0x%" PRIxPTR ", len=%" PRIuS ")",
- (uintptr_t) ptr, size);
-#ifdef TODO_REENABLE_STACK_TRACING
- DumpStackTrace(1, RawInfoStackDumper, NULL);
-#endif
- }
-}
-
-static void SbrkHook(const void* result, ptrdiff_t increment) {
- if (FLAGS_mmap_log) { // log it
- RAW_LOG(INFO, "sbrk(inc=%" PRIdS ") = 0x%" PRIxPTR "",
- increment, (uintptr_t) result);
-#ifdef TODO_REENABLE_STACK_TRACING
- DumpStackTrace(1, RawInfoStackDumper, NULL);
-#endif
- }
-}
-
-//----------------------------------------------------------------------
-// Starting/stopping/dumping
-//----------------------------------------------------------------------
-
-extern "C" void HeapProfilerStart(const char* prefix) {
- SpinLockHolder l(&heap_lock);
-
- if (is_on) return;
-
- is_on = true;
-
- RAW_VLOG(0, "Starting tracking the heap");
-
- // This should be done before the hooks are set up, since it should
- // call new, and we want that to be accounted for correctly.
- MallocExtension::Initialize();
-
- if (FLAGS_only_mmap_profile) {
- FLAGS_mmap_profile = true;
- }
-
- if (FLAGS_mmap_profile) {
- // Ask MemoryRegionMap to record all mmap, mremap, and sbrk
- // call stack traces of at least size kMaxStackDepth:
- MemoryRegionMap::Init(HeapProfileTable::kMaxStackDepth,
- /* use_buckets */ true);
- }
-
- if (FLAGS_mmap_log) {
- // Install our hooks to do the logging:
- RAW_CHECK(MallocHook::AddMmapHook(&MmapHook), "");
- RAW_CHECK(MallocHook::AddMremapHook(&MremapHook), "");
- RAW_CHECK(MallocHook::AddMunmapHook(&MunmapHook), "");
- RAW_CHECK(MallocHook::AddSbrkHook(&SbrkHook), "");
- }
-
- heap_profiler_memory =
- LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena());
-
- // Reserve space now for the heap profiler, so we can still write a
- // heap profile even if the application runs out of memory.
- global_profiler_buffer =
- reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize));
-
- heap_profile = new(ProfilerMalloc(sizeof(HeapProfileTable)))
- HeapProfileTable(ProfilerMalloc, ProfilerFree, FLAGS_mmap_profile);
-
- last_dump_alloc = 0;
- last_dump_free = 0;
- high_water_mark = 0;
- last_dump_time = 0;
-
- // We do not reset dump_count so if the user does a sequence of
- // HeapProfilerStart/HeapProfileStop, we will get a continuous
- // sequence of profiles.
-
- if (FLAGS_only_mmap_profile == false) {
- // Now set the hooks that capture new/delete and malloc/free.
- RAW_CHECK(MallocHook::AddNewHook(&NewHook), "");
- RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), "");
- }
-
- // Copy filename prefix
- RAW_DCHECK(filename_prefix == NULL, "");
- const int prefix_length = strlen(prefix);
- filename_prefix = reinterpret_cast<char*>(ProfilerMalloc(prefix_length + 1));
- memcpy(filename_prefix, prefix, prefix_length);
- filename_prefix[prefix_length] = '\0';
-}
-
-extern "C" int IsHeapProfilerRunning() {
- SpinLockHolder l(&heap_lock);
- return is_on ? 1 : 0; // return an int, because C code doesn't have bool
-}
-
-extern "C" void HeapProfilerStop() {
- SpinLockHolder l(&heap_lock);
-
- if (!is_on) return;
-
- if (FLAGS_only_mmap_profile == false) {
- // Unset our new/delete hooks, checking they were set:
- RAW_CHECK(MallocHook::RemoveNewHook(&NewHook), "");
- RAW_CHECK(MallocHook::RemoveDeleteHook(&DeleteHook), "");
- }
- if (FLAGS_mmap_log) {
- // Restore mmap/sbrk hooks, checking that our hooks were set:
- RAW_CHECK(MallocHook::RemoveMmapHook(&MmapHook), "");
- RAW_CHECK(MallocHook::RemoveMremapHook(&MremapHook), "");
- RAW_CHECK(MallocHook::RemoveSbrkHook(&SbrkHook), "");
- RAW_CHECK(MallocHook::RemoveMunmapHook(&MunmapHook), "");
- }
-
- // free profile
- heap_profile->~HeapProfileTable();
- ProfilerFree(heap_profile);
- heap_profile = NULL;
-
- // free output-buffer memory
- ProfilerFree(global_profiler_buffer);
-
- // free prefix
- ProfilerFree(filename_prefix);
- filename_prefix = NULL;
-
- if (!LowLevelAlloc::DeleteArena(heap_profiler_memory)) {
- RAW_LOG(FATAL, "Memory leak in HeapProfiler:");
- }
-
- if (FLAGS_mmap_profile) {
- MemoryRegionMap::Shutdown();
- }
-
- is_on = false;
-}
-
-extern "C" void HeapProfilerDump(const char *reason) {
- SpinLockHolder l(&heap_lock);
- if (is_on && !dumping) {
- DumpProfileLocked(reason);
- }
-}
-
-// Signal handler that is registered when a user selectable signal
-// number is defined in the environment variable HEAPPROFILESIGNAL.
-static void HeapProfilerDumpSignal(int signal_number) {
- (void)signal_number;
- if (!heap_lock.TryLock()) {
- return;
- }
- if (is_on && !dumping) {
- DumpProfileLocked("signal");
- }
- heap_lock.Unlock();
-}
-
-
-//----------------------------------------------------------------------
-// Initialization/finalization code
-//----------------------------------------------------------------------
-
-// Initialization code
-static void HeapProfilerInit() {
- // Everything after this point is for setting up the profiler based on envvar
- char fname[PATH_MAX];
- if (!GetUniquePathFromEnv("HEAPPROFILE", fname)) {
- return;
- }
- // We do a uid check so we don't write out files in a setuid executable.
-#ifdef HAVE_GETEUID
- if (getuid() != geteuid()) {
- RAW_LOG(WARNING, ("HeapProfiler: ignoring HEAPPROFILE because "
- "program seems to be setuid\n"));
- return;
- }
-#endif
-
- char *signal_number_str = getenv("HEAPPROFILESIGNAL");
- if (signal_number_str != NULL) {
- long int signal_number = strtol(signal_number_str, NULL, 10);
- intptr_t old_signal_handler = reinterpret_cast<intptr_t>(signal(signal_number, HeapProfilerDumpSignal));
- if (old_signal_handler == reinterpret_cast<intptr_t>(SIG_ERR)) {
- RAW_LOG(FATAL, "Failed to set signal. Perhaps signal number %s is invalid\n", signal_number_str);
- } else if (old_signal_handler == 0) {
- RAW_LOG(INFO,"Using signal %d as heap profiling switch", signal_number);
- } else {
- RAW_LOG(FATAL, "Signal %d already in use\n", signal_number);
- }
- }
-
- HeapProfileTable::CleanupOldProfiles(fname);
-
- HeapProfilerStart(fname);
-}
-
-// class used for finalization -- dumps the heap-profile at program exit
-struct HeapProfileEndWriter {
- ~HeapProfileEndWriter() {
- char buf[128];
- if (heap_profile) {
- const HeapProfileTable::Stats& total = heap_profile->total();
- const int64 inuse_bytes = total.alloc_size - total.free_size;
-
- if ((inuse_bytes >> 20) > 0) {
- snprintf(buf, sizeof(buf), ("Exiting, %" PRId64 " MB in use"),
- inuse_bytes >> 20);
- } else if ((inuse_bytes >> 10) > 0) {
- snprintf(buf, sizeof(buf), ("Exiting, %" PRId64 " kB in use"),
- inuse_bytes >> 10);
- } else {
- snprintf(buf, sizeof(buf), ("Exiting, %" PRId64 " bytes in use"),
- inuse_bytes);
- }
- } else {
- snprintf(buf, sizeof(buf), ("Exiting"));
- }
- HeapProfilerDump(buf);
- }
-};
-
-// We want to make sure tcmalloc is up and running before starting the profiler
-static const TCMallocGuard tcmalloc_initializer;
-REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit());
-static HeapProfileEndWriter heap_profile_end_writer;
diff --git a/src/third_party/gperftools-2.5/src/internal_logging.cc b/src/third_party/gperftools-2.5/src/internal_logging.cc
deleted file mode 100644
index 708fa650974..00000000000
--- a/src/third_party/gperftools-2.5/src/internal_logging.cc
+++ /dev/null
@@ -1,192 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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.
-
-// ---
-// Sanjay Ghemawat <opensource@google.com>
-
-#include <config.h>
-#include "internal_logging.h"
-#include <stdarg.h> // for va_end, va_start
-#include <stdio.h> // for vsnprintf, va_list, etc
-#include <stdlib.h> // for abort
-#include <string.h> // for strlen, memcpy
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for write()
-#endif
-
-#include <gperftools/malloc_extension.h>
-#include "base/logging.h" // for perftools_vsnprintf
-#include "base/spinlock.h" // for SpinLockHolder, SpinLock
-
-// Variables for storing crash output. Allocated statically since we
-// may not be able to heap-allocate while crashing.
-static SpinLock crash_lock(base::LINKER_INITIALIZED);
-static bool crashed = false;
-static const int kStatsBufferSize = 16 << 10;
-static char stats_buffer[kStatsBufferSize] = { 0 };
-
-namespace tcmalloc {
-
-static void WriteMessage(const char* msg, int length) {
- write(STDERR_FILENO, msg, length);
-}
-
-void (*log_message_writer)(const char* msg, int length) = WriteMessage;
-
-
-class Logger {
- public:
- bool Add(const LogItem& item);
- bool AddStr(const char* str, int n);
- bool AddNum(uint64_t num, int base); // base must be 10 or 16.
-
- static const int kBufSize = 200;
- char* p_;
- char* end_;
- char buf_[kBufSize];
-};
-
-void Log(LogMode mode, const char* filename, int line,
- LogItem a, LogItem b, LogItem c, LogItem d) {
- Logger state;
- state.p_ = state.buf_;
- state.end_ = state.buf_ + sizeof(state.buf_);
- state.AddStr(filename, strlen(filename))
- && state.AddStr(":", 1)
- && state.AddNum(line, 10)
- && state.AddStr("]", 1)
- && state.Add(a)
- && state.Add(b)
- && state.Add(c)
- && state.Add(d);
-
- // Teminate with newline
- if (state.p_ >= state.end_) {
- state.p_ = state.end_ - 1;
- }
- *state.p_ = '\n';
- state.p_++;
-
- int msglen = state.p_ - state.buf_;
- if (mode == kLog) {
- (*log_message_writer)(state.buf_, msglen);
- return;
- }
-
- bool first_crash = false;
- {
- SpinLockHolder l(&crash_lock);
- if (!crashed) {
- crashed = true;
- first_crash = true;
- }
- }
-
- (*log_message_writer)(state.buf_, msglen);
- if (first_crash && mode == kCrashWithStats) {
- MallocExtension::instance()->GetStats(stats_buffer, kStatsBufferSize);
- (*log_message_writer)(stats_buffer, strlen(stats_buffer));
- }
-
- abort();
-}
-
-bool Logger::Add(const LogItem& item) {
- // Separate items with spaces
- if (p_ < end_) {
- *p_ = ' ';
- p_++;
- }
-
- switch (item.tag_) {
- case LogItem::kStr:
- return AddStr(item.u_.str, strlen(item.u_.str));
- case LogItem::kUnsigned:
- return AddNum(item.u_.unum, 10);
- case LogItem::kSigned:
- if (item.u_.snum < 0) {
- // The cast to uint64_t is intentionally before the negation
- // so that we do not attempt to negate -2^63.
- return AddStr("-", 1)
- && AddNum(- static_cast<uint64_t>(item.u_.snum), 10);
- } else {
- return AddNum(static_cast<uint64_t>(item.u_.snum), 10);
- }
- case LogItem::kPtr:
- return AddStr("0x", 2)
- && AddNum(reinterpret_cast<uintptr_t>(item.u_.ptr), 16);
- default:
- return false;
- }
-}
-
-bool Logger::AddStr(const char* str, int n) {
- if (end_ - p_ < n) {
- return false;
- } else {
- memcpy(p_, str, n);
- p_ += n;
- return true;
- }
-}
-
-bool Logger::AddNum(uint64_t num, int base) {
- static const char kDigits[] = "0123456789abcdef";
- char space[22]; // more than enough for 2^64 in smallest supported base (10)
- char* end = space + sizeof(space);
- char* pos = end;
- do {
- pos--;
- *pos = kDigits[num % base];
- num /= base;
- } while (num > 0 && pos > space);
- return AddStr(pos, end - pos);
-}
-
-} // end tcmalloc namespace
-
-void TCMalloc_Printer::printf(const char* format, ...) {
- if (left_ > 0) {
- va_list ap;
- va_start(ap, format);
- const int r = perftools_vsnprintf(buf_, left_, format, ap);
- va_end(ap);
- if (r < 0) {
- // Perhaps an old glibc that returns -1 on truncation?
- left_ = 0;
- } else if (r > left_) {
- // Truncation
- left_ = 0;
- } else {
- left_ -= r;
- buf_ += r;
- }
- }
-}
diff --git a/src/third_party/gperftools-2.5/src/internal_logging.h b/src/third_party/gperftools-2.5/src/internal_logging.h
deleted file mode 100644
index 0c300c3e20d..00000000000
--- a/src/third_party/gperftools-2.5/src/internal_logging.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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>
-//
-// Internal logging and related utility routines.
-
-#ifndef TCMALLOC_INTERNAL_LOGGING_H_
-#define TCMALLOC_INTERNAL_LOGGING_H_
-
-#include <config.h>
-#include <stddef.h> // for size_t
-#if defined HAVE_STDINT_H
-#include <stdint.h>
-#elif defined HAVE_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <sys/types.h>
-#endif
-
-//-------------------------------------------------------------------
-// Utility routines
-//-------------------------------------------------------------------
-
-// Safe logging helper: we write directly to the stderr file
-// descriptor and avoid FILE buffering because that may invoke
-// malloc().
-//
-// Example:
-// Log(kLog, __FILE__, __LINE__, "error", bytes);
-
-namespace tcmalloc {
-enum LogMode {
- kLog, // Just print the message
- kCrash, // Print the message and crash
- kCrashWithStats // Print the message, some stats, and crash
-};
-
-class Logger;
-
-// A LogItem holds any of the argument types that can be passed to Log()
-class LogItem {
- public:
- LogItem() : tag_(kEnd) { }
- LogItem(const char* v) : tag_(kStr) { u_.str = v; }
- LogItem(int v) : tag_(kSigned) { u_.snum = v; }
- LogItem(long v) : tag_(kSigned) { u_.snum = v; }
- LogItem(long long v) : tag_(kSigned) { u_.snum = v; }
- LogItem(unsigned int v) : tag_(kUnsigned) { u_.unum = v; }
- LogItem(unsigned long v) : tag_(kUnsigned) { u_.unum = v; }
- LogItem(unsigned long long v) : tag_(kUnsigned) { u_.unum = v; }
- LogItem(const void* v) : tag_(kPtr) { u_.ptr = v; }
- private:
- friend class Logger;
- enum Tag {
- kStr,
- kSigned,
- kUnsigned,
- kPtr,
- kEnd
- };
- Tag tag_;
- union {
- const char* str;
- const void* ptr;
- int64_t snum;
- uint64_t unum;
- } u_;
-};
-
-extern PERFTOOLS_DLL_DECL void Log(LogMode mode, const char* filename, int line,
- LogItem a, LogItem b = LogItem(),
- LogItem c = LogItem(), LogItem d = LogItem());
-
-// Tests can override this function to collect logging messages.
-extern PERFTOOLS_DLL_DECL void (*log_message_writer)(const char* msg, int length);
-
-} // end tcmalloc namespace
-
-// Like assert(), but executed even in NDEBUG mode
-#undef CHECK_CONDITION
-#define CHECK_CONDITION(cond) \
-do { \
- if (!(cond)) { \
- ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, #cond); \
- } \
-} while (0)
-
-// Our own version of assert() so we can avoid hanging by trying to do
-// all kinds of goofy printing while holding the malloc lock.
-#ifndef NDEBUG
-#define ASSERT(cond) CHECK_CONDITION(cond)
-#else
-#define ASSERT(cond) ((void) 0)
-#endif
-
-// Print into buffer
-class TCMalloc_Printer {
- private:
- char* buf_; // Where should we write next
- int left_; // Space left in buffer (including space for \0)
-
- public:
- // REQUIRES: "length > 0"
- TCMalloc_Printer(char* buf, int length) : buf_(buf), left_(length) {
- buf[0] = '\0';
- }
-
- void printf(const char* format, ...)
-#ifdef HAVE___ATTRIBUTE__
- __attribute__ ((__format__ (__printf__, 2, 3)))
-#endif
-;
-};
-
-#endif // TCMALLOC_INTERNAL_LOGGING_H_
diff --git a/src/third_party/gperftools-2.5/src/libc_override.h b/src/third_party/gperftools-2.5/src/libc_override.h
deleted file mode 100644
index c01a97ca614..00000000000
--- a/src/third_party/gperftools-2.5/src/libc_override.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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 <gperftools/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/src/third_party/gperftools-2.5/src/libc_override_gcc_and_weak.h b/src/third_party/gperftools-2.5/src/libc_override_gcc_and_weak.h
deleted file mode 100644
index 26c4ff8d31b..00000000000
--- a/src/third_party/gperftools-2.5/src/libc_override_gcc_and_weak.h
+++ /dev/null
@@ -1,172 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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 <gperftools/tcmalloc.h>
-
-#include "getenv_safe.h" // TCMallocGetenvSafe
-#include "base/commandlineflags.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), used))
-
-void* operator new(size_t size)
- ALIAS(tc_new);
-void operator delete(void* p) noexcept
- ALIAS(tc_delete);
-void* operator new[](size_t size)
- ALIAS(tc_newarray);
-void operator delete[](void* p) noexcept
- ALIAS(tc_deletearray);
-void* operator new(size_t size, const std::nothrow_t& nt) noexcept
- ALIAS(tc_new_nothrow);
-void* operator new[](size_t size, const std::nothrow_t& nt) noexcept
- ALIAS(tc_newarray_nothrow);
-void operator delete(void* p, const std::nothrow_t& nt) noexcept
- ALIAS(tc_delete_nothrow);
-void operator delete[](void* p, const std::nothrow_t& nt) noexcept
- ALIAS(tc_deletearray_nothrow);
-
-#if defined(ENABLE_SIZED_DELETE)
-
-void operator delete(void *p, size_t size) noexcept
- ALIAS(tc_delete_sized);
-void operator delete[](void *p, size_t size) noexcept
- ALIAS(tc_deletearray_sized);
-
-#elif defined(ENABLE_DYNAMIC_SIZED_DELETE) && \
- (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
-
-static void delegate_sized_delete(void *p, size_t s) noexcept {
- (operator delete)(p);
-}
-
-static void delegate_sized_deletearray(void *p, size_t s) noexcept {
- (operator delete[])(p);
-}
-
-extern "C" __attribute__((weak))
-int tcmalloc_sized_delete_enabled(void);
-
-static bool sized_delete_enabled(void) {
- if (tcmalloc_sized_delete_enabled != 0) {
- return !!tcmalloc_sized_delete_enabled();
- }
-
- const char *flag = TCMallocGetenvSafe("TCMALLOC_ENABLE_SIZED_DELETE");
- return tcmalloc::commandlineflags::StringToBool(flag, false);
-}
-
-extern "C" {
-
-static void *resolve_delete_sized(void) {
- if (sized_delete_enabled()) {
- return reinterpret_cast<void *>(tc_delete_sized);
- }
- return reinterpret_cast<void *>(delegate_sized_delete);
-}
-
-static void *resolve_deletearray_sized(void) {
- if (sized_delete_enabled()) {
- return reinterpret_cast<void *>(tc_deletearray_sized);
- }
- return reinterpret_cast<void *>(delegate_sized_deletearray);
-}
-
-}
-
-void operator delete(void *p, size_t size) noexcept
- __attribute__((ifunc("resolve_delete_sized")));
-void operator delete[](void *p, size_t size) noexcept
- __attribute__((ifunc("resolve_deletearray_sized")));
-
-#else /* !ENABLE_SIZED_DELETE && !ENABLE_DYN_SIZED_DELETE */
-
-void operator delete(void *p, size_t size) noexcept
- ALIAS(tc_delete);
-void operator delete[](void *p, size_t size) noexcept
- ALIAS(tc_deletearray);
-
-#endif /* !ENABLE_SIZED_DELETE && !ENABLE_DYN_SIZED_DELETE */
-
-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);
-#ifndef __UCLIBC__
- void malloc_stats(void) __THROW ALIAS(tc_malloc_stats);
-#endif
- 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);
-#if defined(__ANDROID__)
- size_t malloc_usable_size(const void* p) __THROW
- ALIAS(tc_malloc_size);
-#else
- size_t malloc_usable_size(void* p) __THROW ALIAS(tc_malloc_size);
-#endif
-} // 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/src/third_party/gperftools-2.5/src/libc_override_glibc.h b/src/third_party/gperftools-2.5/src/libc_override_glibc.h
deleted file mode 100644
index 014aff038bd..00000000000
--- a/src/third_party/gperftools-2.5/src/libc_override_glibc.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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__
-#include <gperftools/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/src/third_party/gperftools-2.5/src/libc_override_osx.h b/src/third_party/gperftools-2.5/src/libc_override_osx.h
deleted file mode 100644
index b801f22a452..00000000000
--- a/src/third_party/gperftools-2.5/src/libc_override_osx.h
+++ /dev/null
@@ -1,281 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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 <gperftools/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>
-
-namespace tcmalloc {
- void CentralCacheLockAll();
- void CentralCacheUnlockAll();
-}
-
-// from AvailabilityMacros.h
-#if defined(MAC_OS_X_VERSION_10_6) && \
- MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-extern "C" {
- // This function is only available on 10.6 (and later) but the
- // LibSystem headers do not use AvailabilityMacros.h to handle weak
- // importing automatically. This prototype is a copy of the one in
- // <malloc/malloc.h> with the WEAK_IMPORT_ATTRBIUTE added.
- extern malloc_zone_t *malloc_default_purgeable_zone(void)
- WEAK_IMPORT_ATTRIBUTE;
-}
-#endif
-
-// 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) {
- tcmalloc::CentralCacheLockAll();
-}
-
-void mi_force_unlock(malloc_zone_t *zone) {
- tcmalloc::CentralCacheUnlockAll();
-}
-
-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. This only needs to
- // happen when actually running on OS X 10.6 and higher (note the
- // ifdef above only checks if we were *compiled* with 10.6 or
- // higher; at runtime we have to check if this symbol is defined.)
- if (malloc_default_purgeable_zone) {
- 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/src/third_party/gperftools-2.5/src/libc_override_redefine.h b/src/third_party/gperftools-2.5/src/libc_override_redefine.h
deleted file mode 100644
index 72679ef38b8..00000000000
--- a/src/third_party/gperftools-2.5/src/libc_override_redefine.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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_
-
-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);
-}
-
-#ifdef ENABLE_SIZED_DELETE
-void operator delete(void* p, size_t s) throw() { tc_delete_sized(p, s); }
-void operator delete[](void* p, size_t s) throw(){ tc_deletearray_sized(p); }
-#endif
-
-extern "C" {
- void* malloc(size_t s) { return tc_malloc(s); }
- void free(void* p) { tc_free(p); }
- void* realloc(void* p, size_t s) { return tc_realloc(p, s); }
- void* calloc(size_t n, size_t s) { return tc_calloc(n, s); }
- void cfree(void* p) { tc_cfree(p); }
- void* memalign(size_t a, size_t s) { return tc_memalign(a, s); }
- void* valloc(size_t s) { return tc_valloc(s); }
- void* pvalloc(size_t s) { return tc_pvalloc(s); }
- int posix_memalign(void** r, size_t a, size_t s) {
- return tc_posix_memalign(r, a, s);
- }
- void malloc_stats(void) { tc_malloc_stats(); }
- int mallopt(int cmd, int v) { return tc_mallopt(cmd, v); }
-#ifdef HAVE_STRUCT_MALLINFO
- struct mallinfo mallinfo(void) { return tc_mallinfo(); }
-#endif
- size_t malloc_size(void* p) { return tc_malloc_size(p); }
- size_t malloc_usable_size(void* p) { 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/src/third_party/gperftools-2.5/src/linked_list.h b/src/third_party/gperftools-2.5/src/linked_list.h
deleted file mode 100644
index 66a07410760..00000000000
--- a/src/third_party/gperftools-2.5/src/linked_list.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-//
-// Some very basic linked list functions for dealing with using void * as
-// storage.
-
-#ifndef TCMALLOC_LINKED_LIST_H_
-#define TCMALLOC_LINKED_LIST_H_
-
-#include <stddef.h>
-
-namespace tcmalloc {
-
-inline void *SLL_Next(void *t) {
- return *(reinterpret_cast<void**>(t));
-}
-
-inline void SLL_SetNext(void *t, void *n) {
- *(reinterpret_cast<void**>(t)) = n;
-}
-
-inline void SLL_Push(void **list, void *element) {
- SLL_SetNext(element, *list);
- *list = element;
-}
-
-inline void *SLL_Pop(void **list) {
- void *result = *list;
- *list = SLL_Next(*list);
- return result;
-}
-
-// Remove N elements from a linked list to which head points. head will be
-// modified to point to the new head. start and end will point to the first
-// and last nodes of the range. Note that end will point to NULL after this
-// function is called.
-inline void SLL_PopRange(void **head, int N, void **start, void **end) {
- if (N == 0) {
- *start = NULL;
- *end = NULL;
- return;
- }
-
- void *tmp = *head;
- for (int i = 1; i < N; ++i) {
- tmp = SLL_Next(tmp);
- }
-
- *start = *head;
- *end = tmp;
- *head = SLL_Next(tmp);
- // Unlink range from list.
- SLL_SetNext(tmp, NULL);
-}
-
-inline void SLL_PushRange(void **head, void *start, void *end) {
- if (!start) return;
- SLL_SetNext(end, *head);
- *head = start;
-}
-
-inline size_t SLL_Size(void *head) {
- int count = 0;
- while (head) {
- count++;
- head = SLL_Next(head);
- }
- return count;
-}
-
-} // namespace tcmalloc
-
-#endif // TCMALLOC_LINKED_LIST_H_
diff --git a/src/third_party/gperftools-2.5/src/malloc_extension.cc b/src/third_party/gperftools-2.5/src/malloc_extension.cc
deleted file mode 100644
index a7000f2fe3c..00000000000
--- a/src/third_party/gperftools-2.5/src/malloc_extension.cc
+++ /dev/null
@@ -1,395 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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>
-
-#include <config.h>
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#if defined HAVE_STDINT_H
-#include <stdint.h>
-#elif defined HAVE_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <sys/types.h>
-#endif
-#include <string>
-#include "base/dynamic_annotations.h"
-#include "base/sysinfo.h" // for FillProcSelfMaps
-#ifndef NO_HEAP_CHECK
-#include "gperftools/heap-checker.h"
-#endif
-#include "gperftools/malloc_extension.h"
-#include "gperftools/malloc_extension_c.h"
-#include "maybe_threads.h"
-#include "base/googleinit.h"
-
-using STL_NAMESPACE::string;
-using STL_NAMESPACE::vector;
-
-static void DumpAddressMap(string* result) {
- *result += "\nMAPPED_LIBRARIES:\n";
- // We keep doubling until we get a fit
- const size_t old_resultlen = result->size();
- for (int amap_size = 10240; amap_size < 10000000; amap_size *= 2) {
- result->resize(old_resultlen + amap_size);
- bool wrote_all = false;
- const int bytes_written =
- tcmalloc::FillProcSelfMaps(&((*result)[old_resultlen]), amap_size,
- &wrote_all);
- if (wrote_all) { // we fit!
- (*result)[old_resultlen + bytes_written] = '\0';
- result->resize(old_resultlen + bytes_written);
- return;
- }
- }
- result->reserve(old_resultlen); // just don't print anything
-}
-
-// Note: this routine is meant to be called before threads are spawned.
-void MallocExtension::Initialize() {
- static bool initialize_called = false;
-
- if (initialize_called) return;
- initialize_called = true;
-
-#ifdef __GLIBC__
- // GNU libc++ versions 3.3 and 3.4 obey the environment variables
- // GLIBCPP_FORCE_NEW and GLIBCXX_FORCE_NEW respectively. Setting
- // one of these variables forces the STL default allocator to call
- // new() or delete() for each allocation or deletion. Otherwise
- // the STL allocator tries to avoid the high cost of doing
- // allocations by pooling memory internally. However, tcmalloc
- // does allocations really fast, especially for the types of small
- // items one sees in STL, so it's better off just using us.
- // TODO: control whether we do this via an environment variable?
- setenv("GLIBCPP_FORCE_NEW", "1", false /* no overwrite*/);
- setenv("GLIBCXX_FORCE_NEW", "1", false /* no overwrite*/);
-
- // Now we need to make the setenv 'stick', which it may not do since
- // the env is flakey before main() is called. But luckily stl only
- // looks at this env var the first time it tries to do an alloc, and
- // caches what it finds. So we just cause an stl alloc here.
- string dummy("I need to be allocated");
- dummy += "!"; // so the definition of dummy isn't optimized out
-#endif /* __GLIBC__ */
-}
-
-// SysAllocator implementation
-SysAllocator::~SysAllocator() {}
-
-// Default implementation -- does nothing
-MallocExtension::~MallocExtension() { }
-bool MallocExtension::VerifyAllMemory() { return true; }
-bool MallocExtension::VerifyNewMemory(const void* p) { return true; }
-bool MallocExtension::VerifyArrayNewMemory(const void* p) { return true; }
-bool MallocExtension::VerifyMallocMemory(const void* p) { return true; }
-
-bool MallocExtension::GetNumericProperty(const char* property, size_t* value) {
- return false;
-}
-
-bool MallocExtension::SetNumericProperty(const char* property, size_t value) {
- return false;
-}
-
-void MallocExtension::GetStats(char* buffer, int length) {
- assert(length > 0);
- buffer[0] = '\0';
-}
-
-bool MallocExtension::MallocMemoryStats(int* blocks, size_t* total,
- int histogram[kMallocHistogramSize]) {
- *blocks = 0;
- *total = 0;
- memset(histogram, 0, sizeof(*histogram) * kMallocHistogramSize);
- return true;
-}
-
-void** MallocExtension::ReadStackTraces(int* sample_period) {
- return NULL;
-}
-
-void** MallocExtension::ReadHeapGrowthStackTraces() {
- return NULL;
-}
-
-void MallocExtension::MarkThreadIdle() {
- // Default implementation does nothing
-}
-
-void MallocExtension::MarkThreadBusy() {
- // Default implementation does nothing
-}
-
-SysAllocator* MallocExtension::GetSystemAllocator() {
- return NULL;
-}
-
-void MallocExtension::SetSystemAllocator(SysAllocator *a) {
- // Default implementation does nothing
-}
-
-void MallocExtension::ReleaseToSystem(size_t num_bytes) {
- // Default implementation does nothing
-}
-
-void MallocExtension::ReleaseFreeMemory() {
- ReleaseToSystem(static_cast<size_t>(-1)); // SIZE_T_MAX
-}
-
-void MallocExtension::SetMemoryReleaseRate(double rate) {
- // Default implementation does nothing
-}
-
-double MallocExtension::GetMemoryReleaseRate() {
- return -1.0;
-}
-
-size_t MallocExtension::GetEstimatedAllocatedSize(size_t size) {
- return size;
-}
-
-size_t MallocExtension::GetAllocatedSize(const 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();
-}
-
-size_t MallocExtension::GetThreadCacheSize() {
- return 0;
-}
-
-void MallocExtension::MarkThreadTemporarilyIdle() {
- // Default implementation does nothing
-}
-
-// The current malloc extension object.
-
-static MallocExtension* current_instance;
-
-static void InitModule() {
- if (current_instance != NULL) {
- return;
- }
- current_instance = new MallocExtension;
-#ifndef NO_HEAP_CHECK
- HeapLeakChecker::IgnoreObject(current_instance);
-#endif
-}
-
-REGISTER_MODULE_INITIALIZER(malloc_extension_init, InitModule())
-
-MallocExtension* MallocExtension::instance() {
- InitModule();
- return current_instance;
-}
-
-void MallocExtension::Register(MallocExtension* implementation) {
- InitModule();
- // When running under valgrind, our custom malloc is replaced with
- // valgrind's one and malloc extensions will not work. (Note:
- // callers should be responsible for checking that they are the
- // malloc that is really being run, before calling Register. This
- // is just here as an extra sanity check.)
- if (!RunningOnValgrind()) {
- current_instance = implementation;
- }
-}
-
-// -----------------------------------------------------------------------
-// Heap sampling support
-// -----------------------------------------------------------------------
-
-namespace {
-
-// Accessors
-uintptr_t Count(void** entry) {
- return reinterpret_cast<uintptr_t>(entry[0]);
-}
-uintptr_t Size(void** entry) {
- return reinterpret_cast<uintptr_t>(entry[1]);
-}
-uintptr_t Depth(void** entry) {
- return reinterpret_cast<uintptr_t>(entry[2]);
-}
-void* PC(void** entry, int i) {
- return entry[3+i];
-}
-
-void PrintCountAndSize(MallocExtensionWriter* writer,
- uintptr_t count, uintptr_t size) {
- char buf[100];
- snprintf(buf, sizeof(buf),
- "%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));
-}
-
-void PrintHeader(MallocExtensionWriter* writer,
- const char* label, void** entries) {
- // Compute the total count and total size
- uintptr_t total_count = 0;
- uintptr_t total_size = 0;
- for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) {
- total_count += Count(entry);
- total_size += Size(entry);
- }
-
- const char* const kTitle = "heap profile: ";
- writer->append(kTitle, strlen(kTitle));
- PrintCountAndSize(writer, total_count, total_size);
- writer->append(" ", 1);
- writer->append(label, strlen(label));
- writer->append("\n", 1);
-}
-
-void PrintStackEntry(MallocExtensionWriter* writer, void** entry) {
- PrintCountAndSize(writer, Count(entry), Size(entry));
-
- for (int i = 0; i < Depth(entry); i++) {
- char buf[32];
- snprintf(buf, sizeof(buf), " %p", PC(entry, i));
- writer->append(buf, strlen(buf));
- }
- writer->append("\n", 1);
-}
-
-}
-
-void MallocExtension::GetHeapSample(MallocExtensionWriter* writer) {
- int sample_period = 0;
- void** entries = ReadStackTraces(&sample_period);
- if (entries == NULL) {
- const char* const kErrorMsg =
- "This malloc implementation does not support sampling.\n"
- "As of 2005/01/26, only tcmalloc supports sampling, and\n"
- "you are probably running a binary that does not use\n"
- "tcmalloc.\n";
- writer->append(kErrorMsg, strlen(kErrorMsg));
- return;
- }
-
- char label[32];
- sprintf(label, "heap_v2/%d", sample_period);
- PrintHeader(writer, label, entries);
- for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) {
- PrintStackEntry(writer, entry);
- }
- delete[] entries;
-
- DumpAddressMap(writer);
-}
-
-void MallocExtension::GetHeapGrowthStacks(MallocExtensionWriter* writer) {
- void** entries = ReadHeapGrowthStackTraces();
- if (entries == NULL) {
- const char* const kErrorMsg =
- "This malloc implementation does not support "
- "ReadHeapGrowthStackTraces().\n"
- "As of 2005/09/27, only tcmalloc supports this, and you\n"
- "are probably running a binary that does not use tcmalloc.\n";
- writer->append(kErrorMsg, strlen(kErrorMsg));
- return;
- }
-
- // Do not canonicalize the stack entries, so that we get a
- // time-ordered list of stack traces, which may be useful if the
- // client wants to focus on the latest stack traces.
- PrintHeader(writer, "growth", entries);
- for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) {
- PrintStackEntry(writer, entry);
- }
- delete[] entries;
-
- DumpAddressMap(writer);
-}
-
-void MallocExtension::Ranges(void* arg, RangeFunction func) {
- // No callbacks by default
-}
-
-void MallocExtension::SizeClasses(void* arg, SizeClassFunction func) {
- // Do nothing by default
-}
-
-// These are C shims that work on the current instance.
-
-#define C_SHIM(fn, retval, paramlist, arglist) \
- extern "C" PERFTOOLS_DLL_DECL retval MallocExtension_##fn paramlist { \
- return MallocExtension::instance()->fn arglist; \
- }
-
-C_SHIM(VerifyAllMemory, int, (void), ());
-C_SHIM(VerifyNewMemory, int, (const void* p), (p));
-C_SHIM(VerifyArrayNewMemory, int, (const void* p), (p));
-C_SHIM(VerifyMallocMemory, int, (const void* p), (p));
-C_SHIM(MallocMemoryStats, int,
- (int* blocks, size_t* total, int histogram[kMallocHistogramSize]),
- (blocks, total, histogram));
-
-C_SHIM(GetStats, void,
- (char* buffer, int buffer_length), (buffer, buffer_length));
-C_SHIM(GetNumericProperty, int,
- (const char* property, size_t* value), (property, value));
-C_SHIM(SetNumericProperty, int,
- (const char* property, size_t value), (property, value));
-C_SHIM(SizeClasses, void,
- (void* arg, void (func)(void*, const base::MallocSizeClass*)),
- (arg, func));
-
-C_SHIM(MarkThreadIdle, void, (void), ());
-C_SHIM(MarkThreadBusy, void, (void), ());
-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, (const void* p), (p));
-C_SHIM(GetThreadCacheSize, size_t, (void), ());
-C_SHIM(MarkThreadTemporarilyIdle, void, (void), ());
-
-// 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/src/third_party/gperftools-2.5/src/malloc_hook-inl.h b/src/third_party/gperftools-2.5/src/malloc_hook-inl.h
deleted file mode 100644
index dbf4d46ed47..00000000000
--- a/src/third_party/gperftools-2.5/src/malloc_hook-inl.h
+++ /dev/null
@@ -1,249 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-//
-// This has the implementation details of malloc_hook that are needed
-// to use malloc-hook inside the tcmalloc system. It does not hold
-// any of the client-facing calls that are used to add new hooks.
-
-#ifndef _MALLOC_HOOK_INL_H_
-#define _MALLOC_HOOK_INL_H_
-
-#include <stddef.h>
-#include <sys/types.h>
-#include "base/atomicops.h"
-#include "base/basictypes.h"
-#include <gperftools/malloc_hook.h>
-
-#include "common.h" // for UNLIKELY
-
-namespace base { namespace internal {
-
-// Capacity of 8 means that HookList is 9 words.
-static const int kHookListCapacity = 8;
-// last entry is reserved for deprecated "singular" hooks. So we have
-// 7 "normal" hooks per list
-static const int kHookListMaxValues = 7;
-static const int kHookListSingularIdx = 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 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
- // blocking (acquires hooklist_spinlock). Returns true on success; false
- // otherwise (failures include invalid value and no space left).
- bool Add(T value);
-
- void FixupPrivEndLocked();
-
- // Removes the first entry matching value from the list. Thread-safe and
- // blocking (acquires hooklist_spinlock). Returns true on success; false
- // otherwise (failures include invalid value and no value found).
- bool Remove(T value);
-
- // Store up to n values of the list in output_array, and return the number of
- // elements stored. Thread-safe and non-blocking. This is fast (one memory
- // access) if the list is empty.
- int Traverse(T* output_array, int n) const;
-
- // Fast inline implementation for fast path of Invoke*Hook.
- bool empty() const {
- return base::subtle::NoBarrier_Load(&priv_end) == 0;
- }
-
- // Used purely to handle deprecated singular hooks
- T GetSingular() const {
- const AtomicWord *place = &priv_data[kHookListSingularIdx];
- return bit_cast<T>(base::subtle::NoBarrier_Load(place));
- }
-
- T ExchangeSingular(T new_val);
-
- // This internal data is not private so that the class is an aggregate and can
- // be initialized by the linker. Don't access this directly. Use the
- // INIT_HOOK_LIST macro in malloc_hook.cc.
-
- // One more than the index of the last valid element in priv_data. During
- // 'Remove' this may be past the last valid element in priv_data, but
- // subsequent values will be 0.
- //
- // Index kHookListCapacity-1 is reserved as 'deprecated' single hook pointer
- AtomicWord priv_end;
- AtomicWord priv_data[kHookListCapacity];
-};
-
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::NewHook> new_hooks_;
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::DeleteHook> delete_hooks_;
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::PreMmapHook> premmap_hooks_;
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MmapHook> mmap_hooks_;
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MmapReplacement> mmap_replacement_;
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MunmapHook> munmap_hooks_;
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MunmapReplacement> munmap_replacement_;
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MremapHook> mremap_hooks_;
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::PreSbrkHook> presbrk_hooks_;
-ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::SbrkHook> sbrk_hooks_;
-
-} } // namespace base::internal
-
-// The following method is DEPRECATED
-inline MallocHook::NewHook MallocHook::GetNewHook() {
- return base::internal::new_hooks_.GetSingular();
-}
-
-inline void MallocHook::InvokeNewHook(const void* p, size_t s) {
- if (UNLIKELY(!base::internal::new_hooks_.empty())) {
- InvokeNewHookSlow(p, s);
- }
-}
-
-// The following method is DEPRECATED
-inline MallocHook::DeleteHook MallocHook::GetDeleteHook() {
- return base::internal::delete_hooks_.GetSingular();
-}
-
-inline void MallocHook::InvokeDeleteHook(const void* p) {
- if (UNLIKELY(!base::internal::delete_hooks_.empty())) {
- InvokeDeleteHookSlow(p);
- }
-}
-
-// The following method is DEPRECATED
-inline MallocHook::PreMmapHook MallocHook::GetPreMmapHook() {
- return base::internal::premmap_hooks_.GetSingular();
-}
-
-inline void MallocHook::InvokePreMmapHook(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset) {
- if (!base::internal::premmap_hooks_.empty()) {
- InvokePreMmapHookSlow(start, size, protection, flags, fd, offset);
- }
-}
-
-// The following method is DEPRECATED
-inline MallocHook::MmapHook MallocHook::GetMmapHook() {
- return base::internal::mmap_hooks_.GetSingular();
-}
-
-inline void MallocHook::InvokeMmapHook(const void* result,
- const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset) {
- if (!base::internal::mmap_hooks_.empty()) {
- InvokeMmapHookSlow(result, start, size, protection, flags, fd, offset);
- }
-}
-
-inline bool MallocHook::InvokeMmapReplacement(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset,
- void** result) {
- if (!base::internal::mmap_replacement_.empty()) {
- return InvokeMmapReplacementSlow(start, size,
- protection, flags,
- fd, offset,
- result);
- }
- return false;
-}
-
-// The following method is DEPRECATED
-inline MallocHook::MunmapHook MallocHook::GetMunmapHook() {
- return base::internal::munmap_hooks_.GetSingular();
-}
-
-inline void MallocHook::InvokeMunmapHook(const void* p, size_t size) {
- if (!base::internal::munmap_hooks_.empty()) {
- InvokeMunmapHookSlow(p, size);
- }
-}
-
-inline bool MallocHook::InvokeMunmapReplacement(
- const void* p, size_t size, int* result) {
- if (!base::internal::mmap_replacement_.empty()) {
- return InvokeMunmapReplacementSlow(p, size, result);
- }
- return false;
-}
-
-// The following method is DEPRECATED
-inline MallocHook::MremapHook MallocHook::GetMremapHook() {
- return base::internal::mremap_hooks_.GetSingular();
-}
-
-inline void MallocHook::InvokeMremapHook(const void* result,
- const void* old_addr,
- size_t old_size,
- size_t new_size,
- int flags,
- const void* new_addr) {
- if (!base::internal::mremap_hooks_.empty()) {
- InvokeMremapHookSlow(result, old_addr, old_size, new_size, flags, new_addr);
- }
-}
-
-// The following method is DEPRECATED
-inline MallocHook::PreSbrkHook MallocHook::GetPreSbrkHook() {
- return base::internal::presbrk_hooks_.GetSingular();
-}
-
-inline void MallocHook::InvokePreSbrkHook(ptrdiff_t increment) {
- if (!base::internal::presbrk_hooks_.empty() && increment != 0) {
- InvokePreSbrkHookSlow(increment);
- }
-}
-
-// The following method is DEPRECATED
-inline MallocHook::SbrkHook MallocHook::GetSbrkHook() {
- return base::internal::sbrk_hooks_.GetSingular();
-}
-
-inline void MallocHook::InvokeSbrkHook(const void* result,
- ptrdiff_t increment) {
- if (!base::internal::sbrk_hooks_.empty() && increment != 0) {
- InvokeSbrkHookSlow(result, increment);
- }
-}
-
-#endif /* _MALLOC_HOOK_INL_H_ */
diff --git a/src/third_party/gperftools-2.5/src/malloc_hook.cc b/src/third_party/gperftools-2.5/src/malloc_hook.cc
deleted file mode 100644
index 57b516d7234..00000000000
--- a/src/third_party/gperftools-2.5/src/malloc_hook.cc
+++ /dev/null
@@ -1,703 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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>
-
-#include <config.h>
-
-// Disable the glibc prototype of mremap(), as older versions of the
-// system headers define this function with only four arguments,
-// whereas newer versions allow an optional fifth argument:
-#ifdef HAVE_MMAP
-# define mremap glibc_mremap
-# include <sys/mman.h>
-# undef mremap
-#endif
-
-#include <stddef.h>
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <algorithm>
-#include "base/logging.h"
-#include "base/spinlock.h"
-#include "maybe_emergency_malloc.h"
-#include "maybe_threads.h"
-#include "malloc_hook-inl.h"
-#include <gperftools/malloc_hook.h>
-
-// This #ifdef should almost never be set. Set NO_TCMALLOC_SAMPLES if
-// you're porting to a system where you really can't get a stacktrace.
-#ifdef NO_TCMALLOC_SAMPLES
- // We use #define so code compiles even if you #include stacktrace.h somehow.
-# define GetStackTrace(stack, depth, skip) (0)
-#else
-# include <gperftools/stacktrace.h>
-#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.
-#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 std::copy;
-
-
-// Declaration of default weak initialization function, that can be overridden
-// by linking-in a strong definition (as heap-checker.cc does). This is
-// extern "C" so that it doesn't trigger gold's --detect-odr-violations warning,
-// which only looks at C++ symbols.
-//
-// This function is declared here as weak, and defined later, rather than a more
-// straightforward simple weak definition, as a workround for an icc compiler
-// issue ((Intel reference 290819). This issue causes icc to resolve weak
-// symbols too early, at compile rather than link time. By declaring it (weak)
-// here, then defining it below after its use, we can avoid the problem.
-extern "C" {
-ATTRIBUTE_WEAK void MallocHook_InitAtFirstAllocation_HeapLeakChecker();
-}
-
-namespace {
-
-void RemoveInitialHooksAndCallInitializers(); // below.
-
-pthread_once_t once = PTHREAD_ONCE_INIT;
-
-// These hooks are installed in MallocHook as the only initial hooks. The first
-// hook that is called will run RemoveInitialHooksAndCallInitializers (see the
-// definition below) and then redispatch to any malloc hooks installed by
-// RemoveInitialHooksAndCallInitializers.
-//
-// Note(llib): there is a possibility of a race in the event that there are
-// multiple threads running before the first allocation. This is pretty
-// difficult to achieve, but if it is then multiple threads may concurrently do
-// allocations. The first caller will call
-// RemoveInitialHooksAndCallInitializers via one of the initial hooks. A
-// concurrent allocation may, depending on timing either:
-// * still have its initial malloc hook installed, run that and block on waiting
-// for the first caller to finish its call to
-// RemoveInitialHooksAndCallInitializers, and proceed normally.
-// * occur some time during the RemoveInitialHooksAndCallInitializers call, at
-// which point there could be no initial hooks and the subsequent hooks that
-// are about to be set up by RemoveInitialHooksAndCallInitializers haven't
-// been installed yet. I think the worst we can get is that some allocations
-// will not get reported to some hooks set by the initializers called from
-// RemoveInitialHooksAndCallInitializers.
-
-void InitialNewHook(const void* ptr, size_t size) {
- perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers);
- MallocHook::InvokeNewHook(ptr, size);
-}
-
-void InitialPreMMapHook(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset) {
- perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers);
- MallocHook::InvokePreMmapHook(start, size, protection, flags, fd, offset);
-}
-
-void InitialPreSbrkHook(ptrdiff_t increment) {
- perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers);
- MallocHook::InvokePreSbrkHook(increment);
-}
-
-// This function is called at most once by one of the above initial malloc
-// hooks. It removes all initial hooks and initializes all other clients that
-// want to get control at the very first memory allocation. The initializers
-// may assume that the initial malloc hooks have been removed. The initializers
-// may set up malloc hooks and allocate memory.
-void RemoveInitialHooksAndCallInitializers() {
- RAW_CHECK(MallocHook::RemoveNewHook(&InitialNewHook), "");
- RAW_CHECK(MallocHook::RemovePreMmapHook(&InitialPreMMapHook), "");
- RAW_CHECK(MallocHook::RemovePreSbrkHook(&InitialPreSbrkHook), "");
-
- // HeapLeakChecker is currently the only module that needs to get control on
- // the first memory allocation, but one can add other modules by following the
- // same weak/strong function pattern.
- MallocHook_InitAtFirstAllocation_HeapLeakChecker();
-}
-
-} // namespace
-
-// Weak default initialization function that must go after its use.
-extern "C" void MallocHook_InitAtFirstAllocation_HeapLeakChecker() {
- // Do nothing.
-}
-
-namespace base { namespace internal {
-
-// This lock is shared between all implementations of HookList::Add & Remove.
-// The potential for contention is very small. This needs to be a SpinLock and
-// not a Mutex since it's possible for Mutex locking to allocate memory (e.g.,
-// per-thread allocation in debug builds), which could cause infinite recursion.
-static SpinLock hooklist_spinlock(base::LINKER_INITIALIZED);
-
-template <typename T>
-bool HookList<T>::Add(T value_as_t) {
- AtomicWord value = bit_cast<AtomicWord>(value_as_t);
- if (value == 0) {
- return false;
- }
- SpinLockHolder l(&hooklist_spinlock);
- // Find the first slot in data that is 0.
- int index = 0;
- while ((index < kHookListMaxValues) &&
- (base::subtle::NoBarrier_Load(&priv_data[index]) != 0)) {
- ++index;
- }
- if (index == kHookListMaxValues) {
- return false;
- }
- AtomicWord prev_num_hooks = base::subtle::Acquire_Load(&priv_end);
- base::subtle::NoBarrier_Store(&priv_data[index], value);
- if (prev_num_hooks <= index) {
- base::subtle::NoBarrier_Store(&priv_end, index + 1);
- }
- return true;
-}
-
-template <typename T>
-void HookList<T>::FixupPrivEndLocked() {
- AtomicWord hooks_end = base::subtle::NoBarrier_Load(&priv_end);
- while ((hooks_end > 0) &&
- (base::subtle::NoBarrier_Load(&priv_data[hooks_end - 1]) == 0)) {
- --hooks_end;
- }
- base::subtle::NoBarrier_Store(&priv_end, hooks_end);
-}
-
-template <typename T>
-bool HookList<T>::Remove(T value_as_t) {
- if (value_as_t == 0) {
- return false;
- }
- SpinLockHolder l(&hooklist_spinlock);
- AtomicWord hooks_end = base::subtle::NoBarrier_Load(&priv_end);
- int index = 0;
- while (index < hooks_end && value_as_t != bit_cast<T>(
- base::subtle::NoBarrier_Load(&priv_data[index]))) {
- ++index;
- }
- if (index == hooks_end) {
- return false;
- }
- base::subtle::NoBarrier_Store(&priv_data[index], 0);
- FixupPrivEndLocked();
- return true;
-}
-
-template <typename T>
-int HookList<T>::Traverse(T* output_array, int n) const {
- AtomicWord hooks_end = base::subtle::Acquire_Load(&priv_end);
- int actual_hooks_end = 0;
- for (int i = 0; i < hooks_end && n > 0; ++i) {
- AtomicWord data = base::subtle::Acquire_Load(&priv_data[i]);
- if (data != 0) {
- *output_array++ = bit_cast<T>(data);
- ++actual_hooks_end;
- --n;
- }
- }
- return actual_hooks_end;
-}
-
-template <typename T>
-T HookList<T>::ExchangeSingular(T value_as_t) {
- AtomicWord value = bit_cast<AtomicWord>(value_as_t);
- AtomicWord old_value;
- SpinLockHolder l(&hooklist_spinlock);
- old_value = base::subtle::NoBarrier_Load(&priv_data[kHookListSingularIdx]);
- base::subtle::NoBarrier_Store(&priv_data[kHookListSingularIdx], value);
- if (value != 0) {
- base::subtle::NoBarrier_Store(&priv_end, kHookListSingularIdx + 1);
- } else {
- FixupPrivEndLocked();
- }
- return bit_cast<T>(old_value);
-}
-
-// Initialize a HookList (optionally with the given initial_value in index 0).
-#define INIT_HOOK_LIST { 0 }
-#define INIT_HOOK_LIST_WITH_VALUE(initial_value) \
- { 1, { reinterpret_cast<AtomicWord>(initial_value) } }
-
-// Explicit instantiation for malloc_hook_test.cc. This ensures all the methods
-// are instantiated.
-template struct HookList<MallocHook::NewHook>;
-
-HookList<MallocHook::NewHook> new_hooks_ =
- INIT_HOOK_LIST_WITH_VALUE(&InitialNewHook);
-HookList<MallocHook::DeleteHook> delete_hooks_ = INIT_HOOK_LIST;
-HookList<MallocHook::PreMmapHook> premmap_hooks_ =
- INIT_HOOK_LIST_WITH_VALUE(&InitialPreMMapHook);
-HookList<MallocHook::MmapHook> mmap_hooks_ = INIT_HOOK_LIST;
-HookList<MallocHook::MunmapHook> munmap_hooks_ = INIT_HOOK_LIST;
-HookList<MallocHook::MremapHook> mremap_hooks_ = INIT_HOOK_LIST;
-HookList<MallocHook::PreSbrkHook> presbrk_hooks_ =
- INIT_HOOK_LIST_WITH_VALUE(InitialPreSbrkHook);
-HookList<MallocHook::SbrkHook> sbrk_hooks_ = INIT_HOOK_LIST;
-
-// These lists contain either 0 or 1 hooks.
-HookList<MallocHook::MmapReplacement> mmap_replacement_ = { 0 };
-HookList<MallocHook::MunmapReplacement> munmap_replacement_ = { 0 };
-
-#undef INIT_HOOK_LIST_WITH_VALUE
-#undef INIT_HOOK_LIST
-
-} } // namespace base::internal
-
-using base::internal::kHookListMaxValues;
-using base::internal::new_hooks_;
-using base::internal::delete_hooks_;
-using base::internal::premmap_hooks_;
-using base::internal::mmap_hooks_;
-using base::internal::mmap_replacement_;
-using base::internal::munmap_hooks_;
-using base::internal::munmap_replacement_;
-using base::internal::mremap_hooks_;
-using base::internal::presbrk_hooks_;
-using base::internal::sbrk_hooks_;
-
-// These are available as C bindings as well as C++, hence their
-// definition outside the MallocHook class.
-extern "C"
-int MallocHook_AddNewHook(MallocHook_NewHook hook) {
- RAW_VLOG(10, "AddNewHook(%p)", hook);
- return new_hooks_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemoveNewHook(MallocHook_NewHook hook) {
- RAW_VLOG(10, "RemoveNewHook(%p)", hook);
- return new_hooks_.Remove(hook);
-}
-
-extern "C"
-int MallocHook_AddDeleteHook(MallocHook_DeleteHook hook) {
- RAW_VLOG(10, "AddDeleteHook(%p)", hook);
- return delete_hooks_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemoveDeleteHook(MallocHook_DeleteHook hook) {
- RAW_VLOG(10, "RemoveDeleteHook(%p)", hook);
- return delete_hooks_.Remove(hook);
-}
-
-extern "C"
-int MallocHook_AddPreMmapHook(MallocHook_PreMmapHook hook) {
- RAW_VLOG(10, "AddPreMmapHook(%p)", hook);
- return premmap_hooks_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemovePreMmapHook(MallocHook_PreMmapHook hook) {
- RAW_VLOG(10, "RemovePreMmapHook(%p)", hook);
- return premmap_hooks_.Remove(hook);
-}
-
-extern "C"
-int MallocHook_SetMmapReplacement(MallocHook_MmapReplacement hook) {
- RAW_VLOG(10, "SetMmapReplacement(%p)", hook);
- // NOTE this is a best effort CHECK. Concurrent sets could succeed since
- // this test is outside of the Add spin lock.
- RAW_CHECK(mmap_replacement_.empty(), "Only one MMapReplacement is allowed.");
- return mmap_replacement_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemoveMmapReplacement(MallocHook_MmapReplacement hook) {
- RAW_VLOG(10, "RemoveMmapReplacement(%p)", hook);
- return mmap_replacement_.Remove(hook);
-}
-
-extern "C"
-int MallocHook_AddMmapHook(MallocHook_MmapHook hook) {
- RAW_VLOG(10, "AddMmapHook(%p)", hook);
- return mmap_hooks_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemoveMmapHook(MallocHook_MmapHook hook) {
- RAW_VLOG(10, "RemoveMmapHook(%p)", hook);
- return mmap_hooks_.Remove(hook);
-}
-
-extern "C"
-int MallocHook_AddMunmapHook(MallocHook_MunmapHook hook) {
- RAW_VLOG(10, "AddMunmapHook(%p)", hook);
- return munmap_hooks_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemoveMunmapHook(MallocHook_MunmapHook hook) {
- RAW_VLOG(10, "RemoveMunmapHook(%p)", hook);
- return munmap_hooks_.Remove(hook);
-}
-
-extern "C"
-int MallocHook_SetMunmapReplacement(MallocHook_MunmapReplacement hook) {
- RAW_VLOG(10, "SetMunmapReplacement(%p)", hook);
- // NOTE this is a best effort CHECK. Concurrent sets could succeed since
- // this test is outside of the Add spin lock.
- RAW_CHECK(munmap_replacement_.empty(),
- "Only one MunmapReplacement is allowed.");
- return munmap_replacement_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemoveMunmapReplacement(MallocHook_MunmapReplacement hook) {
- RAW_VLOG(10, "RemoveMunmapReplacement(%p)", hook);
- return munmap_replacement_.Remove(hook);
-}
-
-extern "C"
-int MallocHook_AddMremapHook(MallocHook_MremapHook hook) {
- RAW_VLOG(10, "AddMremapHook(%p)", hook);
- return mremap_hooks_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemoveMremapHook(MallocHook_MremapHook hook) {
- RAW_VLOG(10, "RemoveMremapHook(%p)", hook);
- return mremap_hooks_.Remove(hook);
-}
-
-extern "C"
-int MallocHook_AddPreSbrkHook(MallocHook_PreSbrkHook hook) {
- RAW_VLOG(10, "AddPreSbrkHook(%p)", hook);
- return presbrk_hooks_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemovePreSbrkHook(MallocHook_PreSbrkHook hook) {
- RAW_VLOG(10, "RemovePreSbrkHook(%p)", hook);
- return presbrk_hooks_.Remove(hook);
-}
-
-extern "C"
-int MallocHook_AddSbrkHook(MallocHook_SbrkHook hook) {
- RAW_VLOG(10, "AddSbrkHook(%p)", hook);
- return sbrk_hooks_.Add(hook);
-}
-
-extern "C"
-int MallocHook_RemoveSbrkHook(MallocHook_SbrkHook hook) {
- RAW_VLOG(10, "RemoveSbrkHook(%p)", hook);
- return sbrk_hooks_.Remove(hook);
-}
-
-// The code below is DEPRECATED.
-extern "C"
-MallocHook_NewHook MallocHook_SetNewHook(MallocHook_NewHook hook) {
- RAW_VLOG(10, "SetNewHook(%p)", hook);
- return new_hooks_.ExchangeSingular(hook);
-}
-
-extern "C"
-MallocHook_DeleteHook MallocHook_SetDeleteHook(MallocHook_DeleteHook hook) {
- RAW_VLOG(10, "SetDeleteHook(%p)", hook);
- return delete_hooks_.ExchangeSingular(hook);
-}
-
-extern "C"
-MallocHook_PreMmapHook MallocHook_SetPreMmapHook(MallocHook_PreMmapHook hook) {
- RAW_VLOG(10, "SetPreMmapHook(%p)", hook);
- return premmap_hooks_.ExchangeSingular(hook);
-}
-
-extern "C"
-MallocHook_MmapHook MallocHook_SetMmapHook(MallocHook_MmapHook hook) {
- RAW_VLOG(10, "SetMmapHook(%p)", hook);
- return mmap_hooks_.ExchangeSingular(hook);
-}
-
-extern "C"
-MallocHook_MunmapHook MallocHook_SetMunmapHook(MallocHook_MunmapHook hook) {
- RAW_VLOG(10, "SetMunmapHook(%p)", hook);
- return munmap_hooks_.ExchangeSingular(hook);
-}
-
-extern "C"
-MallocHook_MremapHook MallocHook_SetMremapHook(MallocHook_MremapHook hook) {
- RAW_VLOG(10, "SetMremapHook(%p)", hook);
- return mremap_hooks_.ExchangeSingular(hook);
-}
-
-extern "C"
-MallocHook_PreSbrkHook MallocHook_SetPreSbrkHook(MallocHook_PreSbrkHook hook) {
- RAW_VLOG(10, "SetPreSbrkHook(%p)", hook);
- return presbrk_hooks_.ExchangeSingular(hook);
-}
-
-extern "C"
-MallocHook_SbrkHook MallocHook_SetSbrkHook(MallocHook_SbrkHook hook) {
- RAW_VLOG(10, "SetSbrkHook(%p)", hook);
- return sbrk_hooks_.ExchangeSingular(hook);
-}
-// End of DEPRECATED code section.
-
-// Note: embedding the function calls inside the traversal of HookList would be
-// very confusing, as it is legal for a hook to remove itself and add other
-// hooks. Doing traversal first, and then calling the hooks ensures we only
-// call the hooks registered at the start.
-#define INVOKE_HOOKS(HookType, hook_list, args) do { \
- HookType hooks[kHookListMaxValues]; \
- int num_hooks = hook_list.Traverse(hooks, kHookListMaxValues); \
- for (int i = 0; i < num_hooks; ++i) { \
- (*hooks[i])args; \
- } \
- } while (0)
-
-// There should only be one replacement. Return the result of the first
-// one, or false if there is none.
-#define INVOKE_REPLACEMENT(HookType, hook_list, args) do { \
- HookType hooks[kHookListMaxValues]; \
- int num_hooks = hook_list.Traverse(hooks, kHookListMaxValues); \
- return (num_hooks > 0 && (*hooks[0])args); \
- } while (0)
-
-
-void MallocHook::InvokeNewHookSlow(const void* p, size_t s) {
- if (tcmalloc::IsEmergencyPtr(p)) {
- return;
- }
- INVOKE_HOOKS(NewHook, new_hooks_, (p, s));
-}
-
-void MallocHook::InvokeDeleteHookSlow(const void* p) {
- if (tcmalloc::IsEmergencyPtr(p)) {
- return;
- }
- INVOKE_HOOKS(DeleteHook, delete_hooks_, (p));
-}
-
-void MallocHook::InvokePreMmapHookSlow(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset) {
- INVOKE_HOOKS(PreMmapHook, premmap_hooks_, (start, size, protection, flags, fd,
- offset));
-}
-
-void MallocHook::InvokeMmapHookSlow(const void* result,
- const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset) {
- INVOKE_HOOKS(MmapHook, mmap_hooks_, (result, start, size, protection, flags,
- fd, offset));
-}
-
-bool MallocHook::InvokeMmapReplacementSlow(const void* start,
- size_t size,
- int protection,
- int flags,
- int fd,
- off_t offset,
- void** result) {
- INVOKE_REPLACEMENT(MmapReplacement, mmap_replacement_,
- (start, size, protection, flags, fd, offset, result));
-}
-
-void MallocHook::InvokeMunmapHookSlow(const void* p, size_t s) {
- INVOKE_HOOKS(MunmapHook, munmap_hooks_, (p, s));
-}
-
-bool MallocHook::InvokeMunmapReplacementSlow(const void* p,
- size_t s,
- int* result) {
- INVOKE_REPLACEMENT(MunmapReplacement, munmap_replacement_, (p, s, result));
-}
-
-void MallocHook::InvokeMremapHookSlow(const void* result,
- const void* old_addr,
- size_t old_size,
- size_t new_size,
- int flags,
- const void* new_addr) {
- INVOKE_HOOKS(MremapHook, mremap_hooks_, (result, old_addr, old_size, new_size,
- flags, new_addr));
-}
-
-void MallocHook::InvokePreSbrkHookSlow(ptrdiff_t increment) {
- INVOKE_HOOKS(PreSbrkHook, presbrk_hooks_, (increment));
-}
-
-void MallocHook::InvokeSbrkHookSlow(const void* result, ptrdiff_t increment) {
- INVOKE_HOOKS(SbrkHook, sbrk_hooks_, (result, increment));
-}
-
-#undef INVOKE_HOOKS
-
-#ifndef NO_TCMALLOC_SAMPLES
-
-DEFINE_ATTRIBUTE_SECTION_VARS(google_malloc);
-DECLARE_ATTRIBUTE_SECTION_VARS(google_malloc);
- // actual functions are in debugallocation.cc or tcmalloc.cc
-DEFINE_ATTRIBUTE_SECTION_VARS(malloc_hook);
-DECLARE_ATTRIBUTE_SECTION_VARS(malloc_hook);
- // actual functions are in this file, malloc_hook.cc, and low_level_alloc.cc
-
-#define ADDR_IN_ATTRIBUTE_SECTION(addr, name) \
- (reinterpret_cast<uintptr_t>(ATTRIBUTE_SECTION_START(name)) <= \
- reinterpret_cast<uintptr_t>(addr) && \
- reinterpret_cast<uintptr_t>(addr) < \
- reinterpret_cast<uintptr_t>(ATTRIBUTE_SECTION_STOP(name)))
-
-// Return true iff 'caller' is a return address within a function
-// that calls one of our hooks via MallocHook:Invoke*.
-// A helper for GetCallerStackTrace.
-static inline bool InHookCaller(const void* caller) {
- return ADDR_IN_ATTRIBUTE_SECTION(caller, google_malloc) ||
- ADDR_IN_ATTRIBUTE_SECTION(caller, malloc_hook);
- // We can use one section for everything except tcmalloc_or_debug
- // due to its special linkage mode, which prevents merging of the sections.
-}
-
-#undef ADDR_IN_ATTRIBUTE_SECTION
-
-static bool checked_sections = false;
-
-static inline void CheckInHookCaller() {
- if (!checked_sections) {
- INIT_ATTRIBUTE_SECTION_VARS(google_malloc);
- if (ATTRIBUTE_SECTION_START(google_malloc) ==
- ATTRIBUTE_SECTION_STOP(google_malloc)) {
- RAW_LOG(ERROR, "google_malloc section is missing, "
- "thus InHookCaller is broken!");
- }
- INIT_ATTRIBUTE_SECTION_VARS(malloc_hook);
- if (ATTRIBUTE_SECTION_START(malloc_hook) ==
- ATTRIBUTE_SECTION_STOP(malloc_hook)) {
- RAW_LOG(ERROR, "malloc_hook section is missing, "
- "thus InHookCaller is broken!");
- }
- checked_sections = true;
- }
-}
-
-#endif // !NO_TCMALLOC_SAMPLES
-
-// We can improve behavior/compactness of this function
-// if we pass a generic test function (with a generic arg)
-// into the implementations for GetStackTrace instead of the skip_count.
-extern "C" int MallocHook_GetCallerStackTrace(void** result, int max_depth,
- int skip_count) {
-#if defined(NO_TCMALLOC_SAMPLES)
- return 0;
-#elif !defined(HAVE_ATTRIBUTE_SECTION_START)
- // Fall back to GetStackTrace and good old but fragile frame skip counts.
- // Note: this path is inaccurate when a hook is not called directly by an
- // allocation function but is daisy-chained through another hook,
- // search for MallocHook::(Get|Set|Invoke)* to find such cases.
- return GetStackTrace(result, max_depth, skip_count + int(DEBUG_MODE));
- // due to -foptimize-sibling-calls in opt mode
- // there's no need for extra frame skip here then
-#else
- CheckInHookCaller();
- // MallocHook caller determination via InHookCaller works, use it:
- static const int kMaxSkip = 32 + 6 + 3;
- // Constant tuned to do just one GetStackTrace call below in practice
- // and not get many frames that we don't actually need:
- // currently max passsed max_depth is 32,
- // max passed/needed skip_count is 6
- // and 3 is to account for some hook daisy chaining.
- static const int kStackSize = kMaxSkip + 1;
- void* stack[kStackSize];
- int depth = GetStackTrace(stack, kStackSize, 1); // skip this function frame
- if (depth == 0) // silenty propagate cases when GetStackTrace does not work
- return 0;
- for (int i = 0; i < depth; ++i) { // stack[0] is our immediate caller
- if (InHookCaller(stack[i])) {
- RAW_VLOG(10, "Found hooked allocator at %d: %p <- %p",
- i, stack[i], stack[i+1]);
- i += 1; // skip hook caller frame
- depth -= i; // correct depth
- if (depth > max_depth) depth = max_depth;
- copy(stack + i, stack + i + depth, result);
- if (depth < max_depth && depth + i == kStackSize) {
- // get frames for the missing depth
- depth +=
- GetStackTrace(result + depth, max_depth - depth, 1 + kStackSize);
- }
- return depth;
- }
- }
- RAW_LOG(WARNING, "Hooked allocator frame not found, returning empty trace");
- // If this happens try increasing kMaxSkip
- // or else something must be wrong with InHookCaller,
- // e.g. for every section used in InHookCaller
- // all functions in that section must be inside the same library.
- return 0;
-#endif
-}
-
-// 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).
-
-#if defined(__linux)
-# include "malloc_hook_mmap_linux.h"
-
-#elif defined(__FreeBSD__)
-# include "malloc_hook_mmap_freebsd.h"
-
-#else
-
-/*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 = mmap(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 = munmap(start, length);
- }
- return result;
-}
-
-#endif
diff --git a/src/third_party/gperftools-2.5/src/malloc_hook_mmap_freebsd.h b/src/third_party/gperftools-2.5/src/malloc_hook_mmap_freebsd.h
deleted file mode 100644
index 8575dcc7c08..00000000000
--- a/src/third_party/gperftools-2.5/src/malloc_hook_mmap_freebsd.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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>
-#include <dlfcn.h>
-
-// Make sure mmap doesn't get #define'd away by <sys/mman.h>
-#undef mmap
-
-// According to the FreeBSD documentation, use syscall if you do not
-// need 64-bit alignment otherwise use __syscall. Indeed, syscall
-// doesn't work correctly in most situations on 64-bit. It's return
-// type is 'int' so for things like SYS_mmap, it actually truncates
-// the returned address to 32-bits.
-#if defined(__amd64__) || defined(__x86_64__)
-# define MALLOC_HOOK_SYSCALL __syscall
-#else
-# define MALLOC_HOOK_SYSCALL syscall
-#endif
-
-
-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_mmap(void *start, size_t length,
- int prot, int flags,
- int fd, off_t offset) __THROW {
- return (void *)MALLOC_HOOK_SYSCALL(SYS_mmap,
- start, length, prot, flags, fd, offset);
-}
-
-static inline void* do_sbrk(intptr_t increment) {
- static void *(*libc_sbrk)(intptr_t);
- if (libc_sbrk == NULL)
- libc_sbrk = (void *(*)(intptr_t))dlsym(RTLD_NEXT, "sbrk");
-
- return libc_sbrk(increment);
-}
-
-
-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_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);
- int result;
- if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) {
- result = MALLOC_HOOK_SYSCALL(SYS_munmap, start, length);
- }
-
- return result;
-}
-
-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) {
- void* result;
- if (!MallocHook::InvokeMmapReplacement(
- start, length, prot, flags, fd, offset, &result)) {
- result = do_mmap(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 = MALLOC_HOOK_SYSCALL(SYS_munmap, start, length);
- }
- return result;
-}
-
-#undef MALLOC_HOOK_SYSCALL
diff --git a/src/third_party/gperftools-2.5/src/malloc_hook_mmap_linux.h b/src/third_party/gperftools-2.5/src/malloc_hook_mmap_linux.h
deleted file mode 100755
index 1c4c7660824..00000000000
--- a/src/third_party/gperftools-2.5/src/malloc_hook_mmap_linux.h
+++ /dev/null
@@ -1,252 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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().
-
-// I test for 64-bit first so I don't have to do things like
-// '#if (defined(__mips__) && !defined(__MIPS64__))' as a mips32 check.
-#if defined(__x86_64__) || defined(__PPC64__) || defined(__aarch64__) || (defined(_MIPS_SIM) && _MIPS_SIM == _ABI64)
-
-static inline void* do_mmap64(void *start, size_t length,
- int prot, int flags,
- int fd, __off64_t offset) __THROW {
- return sys_mmap(start, length, prot, flags, fd, offset);
-}
-
-#define MALLOC_HOOK_HAVE_DO_MMAP64 1
-
-#elif defined(__i386__) || defined(__PPC__) || defined(__mips__) || \
- defined(__arm__)
-
-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;
- }
-
-#ifdef __NR_mmap
- {
- // 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, (int32) length, prot, flags, fd,
- (int32)(off_t) offset };
- result = (void *)syscall(SYS_mmap, args);
- }
-#else
- // Some Linux ports like ARM EABI Linux has no mmap, just mmap2.
- result = MAP_FAILED;
-#endif
-
- out:
- return result;
-}
-
-#define MALLOC_HOOK_HAVE_DO_MMAP64 1
-
-#elif defined(__s390x__)
-
-static inline void* do_mmap64(void *start, size_t length,
- int prot, int flags,
- int fd, __off64_t offset) __THROW {
- // mmap on s390x uses the old syscall interface
- unsigned long args[6] = { (unsigned long) start, (unsigned long) length,
- (unsigned long) prot, (unsigned long) flags,
- (unsigned long) fd, (unsigned long) offset };
- return sys_mmap(args);
-}
-
-#define MALLOC_HOOK_HAVE_DO_MMAP64 1
-
-#endif // #if defined(__x86_64__)
-
-
-#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;
-}
-
-#ifndef __UCLIBC__
-// 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;
-}
-
-#endif
-
-/*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/src/third_party/gperftools-2.5/src/maybe_emergency_malloc.h b/src/third_party/gperftools-2.5/src/maybe_emergency_malloc.h
deleted file mode 100644
index 250ecf01a3f..00000000000
--- a/src/third_party/gperftools-2.5/src/maybe_emergency_malloc.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2014, gperftools Contributors
-// 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.
-
-#ifndef MAYBE_EMERGENCY_MALLOC_H
-#define MAYBE_EMERGENCY_MALLOC_H
-
-#include "config.h"
-
-#ifdef ENABLE_EMERGENCY_MALLOC
-
-#include "emergency_malloc.h"
-
-#else
-
-namespace tcmalloc {
- static inline void *EmergencyMalloc(size_t size) {return NULL;}
- static inline void EmergencyFree(void *p) {}
- static inline void *EmergencyCalloc(size_t n, size_t elem_size) {return NULL;}
- static inline void *EmergencyRealloc(void *old_ptr, size_t new_size) {return NULL;}
-
- static inline bool IsEmergencyPtr(const void *_ptr) {
- return false;
- }
-}
-
-#endif // ENABLE_EMERGENCY_MALLOC
-
-#endif
diff --git a/src/third_party/gperftools-2.5/src/maybe_threads.cc b/src/third_party/gperftools-2.5/src/maybe_threads.cc
deleted file mode 100644
index acfc99a5ae5..00000000000
--- a/src/third_party/gperftools-2.5/src/maybe_threads.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Paul Menage <opensource@google.com>
-//
-// Some wrappers for pthread functions so that we can be LD_PRELOADed
-// against non-pthreads apps.
-//
-// This module will behave very strangely if some pthreads functions
-// exist and others don't.
-
-#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
-// non-zero. I have no idea why ...
-#include <string>
-#include "maybe_threads.h"
-#include "base/basictypes.h"
-#include "base/logging.h"
-
-// __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
-
-// These are the methods we're going to conditionally include.
-extern "C" {
- int pthread_key_create (pthread_key_t*, void (*)(void*))
- __THROW ATTRIBUTE_WEAK;
- int pthread_key_delete (pthread_key_t)
- __THROW ATTRIBUTE_WEAK;
- void *pthread_getspecific(pthread_key_t)
- __THROW ATTRIBUTE_WEAK;
- int pthread_setspecific(pthread_key_t, const void*)
- __THROW ATTRIBUTE_WEAK;
- int pthread_once(pthread_once_t *, void (*)(void))
- ATTRIBUTE_WEAK;
- int pthread_atfork(void (*__prepare) (void),
- void (*__parent) (void),
- void (*__child) (void))
- __THROW ATTRIBUTE_WEAK;
-}
-
-#define MAX_PERTHREAD_VALS 16
-static void *perftools_pthread_specific_vals[MAX_PERTHREAD_VALS];
-static int next_key;
-
-// NOTE: it's similar to bitcast defined in basic_types.h with
-// exception of ignoring sizes mismatch
-template <typename T1, typename T2>
-static T2 memcpy_cast(const T1 &input) {
- T2 output;
- size_t s = sizeof(input);
- if (sizeof(output) < s) {
- s = sizeof(output);
- }
- memcpy(&output, &input, s);
- return output;
-}
-
-int perftools_pthread_key_create(pthread_key_t *key,
- void (*destr_function) (void *)) {
- if (pthread_key_create) {
- return pthread_key_create(key, destr_function);
- } else {
- assert(next_key < MAX_PERTHREAD_VALS);
- *key = memcpy_cast<int, pthread_key_t>(next_key++);
- return 0;
- }
-}
-
-int perftools_pthread_key_delete(pthread_key_t key) {
- if (pthread_key_delete) {
- return pthread_key_delete(key);
- } else {
- return 0;
- }
-}
-
-void *perftools_pthread_getspecific(pthread_key_t key) {
- if (pthread_getspecific) {
- return pthread_getspecific(key);
- } else {
- return perftools_pthread_specific_vals[memcpy_cast<pthread_key_t, int>(key)];
- }
-}
-
-int perftools_pthread_setspecific(pthread_key_t key, void *val) {
- if (pthread_setspecific) {
- return pthread_setspecific(key, val);
- } else {
- perftools_pthread_specific_vals[memcpy_cast<pthread_key_t, int>(key)] = val;
- return 0;
- }
-}
-
-
-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 {
- if (memcmp(ctl, &pthread_once_init, sizeof(*ctl)) == 0) {
- init_routine();
- ++*(char*)(ctl); // make it so it's no longer equal to init
- }
- return 0;
- }
-}
-
-void perftools_pthread_atfork(void (*before)(),
- void (*parent_after)(),
- void (*child_after)()) {
- if (pthread_atfork) {
- int rv = pthread_atfork(before, parent_after, child_after);
- CHECK(rv == 0);
- }
-}
diff --git a/src/third_party/gperftools-2.5/src/maybe_threads.h b/src/third_party/gperftools-2.5/src/maybe_threads.h
deleted file mode 100644
index c6cfdf7d158..00000000000
--- a/src/third_party/gperftools-2.5/src/maybe_threads.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Paul Menage <opensource@google.com>
-
-//-------------------------------------------------------------------
-// Some wrappers for pthread functions so that we can be LD_PRELOADed
-// against non-pthreads apps.
-//-------------------------------------------------------------------
-
-#ifndef GOOGLE_MAYBE_THREADS_H_
-#define GOOGLE_MAYBE_THREADS_H_
-
-#ifdef HAVE_PTHREAD
-#include <pthread.h>
-#endif
-
-int perftools_pthread_key_create(pthread_key_t *key,
- void (*destr_function) (void *));
-int perftools_pthread_key_delete(pthread_key_t key);
-void *perftools_pthread_getspecific(pthread_key_t key);
-int perftools_pthread_setspecific(pthread_key_t key, void *val);
-int perftools_pthread_once(pthread_once_t *ctl,
- void (*init_routine) (void));
-
-// Our wrapper for pthread_atfork. Does _nothing_ when there are no
-// threads. See static_vars.cc:SetupAtForkLocksHandler for only user
-// of this.
-void perftools_pthread_atfork(void (*before)(),
- void (*parent_after)(),
- void (*child_after)());
-
-#endif /* GOOGLE_MAYBE_THREADS_H_ */
diff --git a/src/third_party/gperftools-2.5/src/memfs_malloc.cc b/src/third_party/gperftools-2.5/src/memfs_malloc.cc
deleted file mode 100644
index fd26daff6b2..00000000000
--- a/src/third_party/gperftools-2.5/src/memfs_malloc.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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: Arun Sharma
-//
-// A tcmalloc system allocator that uses a memory based filesystem such as
-// tmpfs or hugetlbfs
-//
-// Since these only exist on linux, we only register this allocator there.
-
-#ifdef __linux
-
-#include <config.h>
-#include <errno.h> // for errno, EINVAL
-#include <inttypes.h> // for PRId64
-#include <limits.h> // for PATH_MAX
-#include <stddef.h> // for size_t, NULL
-#ifdef HAVE_STDINT_H
-#include <stdint.h> // for int64_t, uintptr_t
-#endif
-#include <stdio.h> // for snprintf
-#include <stdlib.h> // for mkstemp
-#include <string.h> // for strerror
-#include <sys/mman.h> // for mmap, MAP_FAILED, etc
-#include <sys/statfs.h> // for fstatfs, statfs
-#include <unistd.h> // for ftruncate, off_t, unlink
-#include <new> // for operator new
-#include <string>
-
-#include <gperftools/malloc_extension.h>
-#include "base/basictypes.h"
-#include "base/googleinit.h"
-#include "base/sysinfo.h"
-#include "internal_logging.h"
-
-// TODO(sanjay): Move the code below into the tcmalloc namespace
-using tcmalloc::kLog;
-using tcmalloc::kCrash;
-using tcmalloc::Log;
-using std::string;
-
-DEFINE_string(memfs_malloc_path, EnvToString("TCMALLOC_MEMFS_MALLOC_PATH", ""),
- "Path where hugetlbfs or tmpfs is mounted. The caller is "
- "responsible for ensuring that the path is unique and does "
- "not conflict with another process");
-DEFINE_int64(memfs_malloc_limit_mb,
- EnvToInt("TCMALLOC_MEMFS_LIMIT_MB", 0),
- "Limit total allocation size to the "
- "specified number of MiB. 0 == no limit.");
-DEFINE_bool(memfs_malloc_abort_on_fail,
- EnvToBool("TCMALLOC_MEMFS_ABORT_ON_FAIL", false),
- "abort() whenever memfs_malloc fails to satisfy an allocation "
- "for any reason.");
-DEFINE_bool(memfs_malloc_ignore_mmap_fail,
- EnvToBool("TCMALLOC_MEMFS_IGNORE_MMAP_FAIL", false),
- "Ignore failures from mmap");
-DEFINE_bool(memfs_malloc_map_private,
- EnvToBool("TCMALLOC_MEMFS_MAP_PRIVATE", false),
- "Use MAP_PRIVATE with mmap");
-
-// Hugetlbfs based allocator for tcmalloc
-class HugetlbSysAllocator: public SysAllocator {
-public:
- explicit HugetlbSysAllocator(SysAllocator* fallback)
- : failed_(true), // To disable allocator until Initialize() is called.
- big_page_size_(0),
- hugetlb_fd_(-1),
- hugetlb_base_(0),
- fallback_(fallback) {
- }
-
- void* Alloc(size_t size, size_t *actual_size, size_t alignment);
- bool Initialize();
-
- bool failed_; // Whether failed to allocate memory.
-
-private:
- void* AllocInternal(size_t size, size_t *actual_size, size_t alignment);
-
- int64 big_page_size_;
- int hugetlb_fd_; // file descriptor for hugetlb
- off_t hugetlb_base_;
-
- SysAllocator* fallback_; // Default system allocator to fall back to.
-};
-static union {
- char buf[sizeof(HugetlbSysAllocator)];
- void *ptr;
-} hugetlb_space;
-
-// No locking needed here since we assume that tcmalloc calls
-// us with an internal lock held (see tcmalloc/system-alloc.cc).
-void* HugetlbSysAllocator::Alloc(size_t size, size_t *actual_size,
- size_t alignment) {
- if (failed_) {
- return fallback_->Alloc(size, actual_size, alignment);
- }
-
- // We don't respond to allocation requests smaller than big_page_size_ unless
- // the caller is ok to take more than they asked for. Used by MetaDataAlloc.
- if (actual_size == NULL && size < big_page_size_) {
- return fallback_->Alloc(size, actual_size, alignment);
- }
-
- // Enforce huge page alignment. Be careful to deal with overflow.
- size_t new_alignment = alignment;
- if (new_alignment < big_page_size_) new_alignment = big_page_size_;
- size_t aligned_size = ((size + new_alignment - 1) /
- new_alignment) * new_alignment;
- if (aligned_size < size) {
- return fallback_->Alloc(size, actual_size, alignment);
- }
-
- void* result = AllocInternal(aligned_size, actual_size, new_alignment);
- if (result != NULL) {
- return result;
- }
- Log(kLog, __FILE__, __LINE__,
- "HugetlbSysAllocator: (failed, allocated)", failed_, hugetlb_base_);
- if (FLAGS_memfs_malloc_abort_on_fail) {
- Log(kCrash, __FILE__, __LINE__,
- "memfs_malloc_abort_on_fail is set");
- }
- return fallback_->Alloc(size, actual_size, alignment);
-}
-
-void* HugetlbSysAllocator::AllocInternal(size_t size, size_t* actual_size,
- size_t alignment) {
- // Ask for extra memory if alignment > pagesize
- size_t extra = 0;
- if (alignment > big_page_size_) {
- extra = alignment - big_page_size_;
- }
-
- // Test if this allocation would put us over the limit.
- off_t limit = FLAGS_memfs_malloc_limit_mb*1024*1024;
- if (limit > 0 && hugetlb_base_ + size + extra > limit) {
- // Disable the allocator when there's less than one page left.
- if (limit - hugetlb_base_ < big_page_size_) {
- Log(kLog, __FILE__, __LINE__, "reached memfs_malloc_limit_mb");
- failed_ = true;
- }
- else {
- Log(kLog, __FILE__, __LINE__,
- "alloc too large (size, bytes left)", size, limit-hugetlb_base_);
- }
- return NULL;
- }
-
- // This is not needed for hugetlbfs, but needed for tmpfs. Annoyingly
- // hugetlbfs returns EINVAL for ftruncate.
- int ret = ftruncate(hugetlb_fd_, hugetlb_base_ + size + extra);
- if (ret != 0 && errno != EINVAL) {
- Log(kLog, __FILE__, __LINE__,
- "ftruncate failed", strerror(errno));
- failed_ = true;
- return NULL;
- }
-
- // Note: size + extra does not overflow since:
- // size + alignment < (1<<NBITS).
- // and extra <= alignment
- // therefore size + extra < (1<<NBITS)
- void *result;
- result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
- FLAGS_memfs_malloc_map_private ? MAP_PRIVATE : MAP_SHARED,
- hugetlb_fd_, hugetlb_base_);
- if (result == reinterpret_cast<void*>(MAP_FAILED)) {
- if (!FLAGS_memfs_malloc_ignore_mmap_fail) {
- Log(kLog, __FILE__, __LINE__,
- "mmap failed (size, error)", size + extra, strerror(errno));
- failed_ = true;
- }
- return NULL;
- }
- uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
-
- // Adjust the return memory so it is aligned
- size_t adjust = 0;
- if ((ptr & (alignment - 1)) != 0) {
- adjust = alignment - (ptr & (alignment - 1));
- }
- ptr += adjust;
- hugetlb_base_ += (size + extra);
-
- if (actual_size) {
- *actual_size = size + extra - adjust;
- }
-
- return reinterpret_cast<void*>(ptr);
-}
-
-bool HugetlbSysAllocator::Initialize() {
- char path[PATH_MAX];
- const int pathlen = FLAGS_memfs_malloc_path.size();
- if (pathlen + 8 > sizeof(path)) {
- Log(kCrash, __FILE__, __LINE__, "XX fatal: memfs_malloc_path too long");
- return false;
- }
- memcpy(path, FLAGS_memfs_malloc_path.data(), pathlen);
- memcpy(path + pathlen, ".XXXXXX", 8); // Also copies terminating \0
-
- int hugetlb_fd = mkstemp(path);
- if (hugetlb_fd == -1) {
- Log(kLog, __FILE__, __LINE__,
- "warning: unable to create memfs_malloc_path",
- path, strerror(errno));
- return false;
- }
-
- // Cleanup memory on process exit
- if (unlink(path) == -1) {
- Log(kCrash, __FILE__, __LINE__,
- "fatal: error unlinking memfs_malloc_path", 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) {
- Log(kCrash, __FILE__, __LINE__,
- "fatal: error fstatfs of memfs_malloc_path", strerror(errno));
- return false;
- }
- int64 page_size = sfs.f_bsize;
-
- hugetlb_fd_ = hugetlb_fd;
- big_page_size_ = page_size;
- failed_ = false;
- return true;
-}
-
-REGISTER_MODULE_INITIALIZER(memfs_malloc, {
- if (FLAGS_memfs_malloc_path.length()) {
- SysAllocator* alloc = MallocExtension::instance()->GetSystemAllocator();
- HugetlbSysAllocator* hp =
- new (hugetlb_space.buf) HugetlbSysAllocator(alloc);
- if (hp->Initialize()) {
- MallocExtension::instance()->SetSystemAllocator(hp);
- }
- }
-});
-
-#endif /* ifdef __linux */
diff --git a/src/third_party/gperftools-2.5/src/memory_region_map.cc b/src/third_party/gperftools-2.5/src/memory_region_map.cc
deleted file mode 100755
index 841d6f3cf85..00000000000
--- a/src/third_party/gperftools-2.5/src/memory_region_map.cc
+++ /dev/null
@@ -1,831 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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: Maxim Lifantsev
- */
-
-//
-// Background and key design points of MemoryRegionMap.
-//
-// MemoryRegionMap is a low-level module with quite atypical requirements that
-// result in some degree of non-triviality of the implementation and design.
-//
-// MemoryRegionMap collects info about *all* memory regions created with
-// mmap, munmap, mremap, sbrk.
-// They key word above is 'all': all that are happening in a process
-// during its lifetime frequently starting even before global object
-// constructor execution.
-//
-// This is needed by the primary client of MemoryRegionMap:
-// HeapLeakChecker uses the regions and the associated stack traces
-// to figure out what part of the memory is the heap:
-// if MemoryRegionMap were to miss some (early) regions, leak checking would
-// stop working correctly.
-//
-// To accomplish the goal of functioning before/during global object
-// constructor execution MemoryRegionMap is done as a singleton service
-// that relies on own on-demand initialized static constructor-less data,
-// and only relies on other low-level modules that can also function properly
-// even before global object constructors run.
-//
-// Accomplishing the goal of collecting data about all mmap, munmap, mremap,
-// sbrk occurrences is a more involved: conceptually to do this one needs to
-// record some bits of data in particular about any mmap or sbrk call,
-// but to do that one needs to allocate memory for that data at some point,
-// but all memory allocations in the end themselves come from an mmap
-// or sbrk call (that's how the address space of the process grows).
-//
-// Also note that we need to do all the above recording from
-// within an mmap/sbrk hook which is sometimes/frequently is made by a memory
-// allocator, including the allocator MemoryRegionMap itself must rely on.
-// In the case of heap-checker usage this includes even the very first
-// mmap/sbrk call happening in the program: heap-checker gets activated due to
-// a link-time installed mmap/sbrk hook and it initializes MemoryRegionMap
-// and asks it to record info about this very first call right from that
-// very first hook invocation.
-//
-// MemoryRegionMap is doing its memory allocations via LowLevelAlloc:
-// unlike more complex standard memory allocator, LowLevelAlloc cooperates with
-// MemoryRegionMap by not holding any of its own locks while it calls mmap
-// to get memory, thus we are able to call LowLevelAlloc from
-// our mmap/sbrk hooks without causing a deadlock in it.
-// For the same reason of deadlock prevention the locking in MemoryRegionMap
-// itself is write-recursive which is an exception to Google's mutex usage.
-//
-// We still need to break the infinite cycle of mmap calling our hook,
-// which asks LowLevelAlloc for memory to record this mmap,
-// which (sometimes) causes mmap, which calls our hook, and so on.
-// We do this as follows: on a recursive call of MemoryRegionMap's
-// mmap/sbrk/mremap hook we record the data about the allocation in a
-// static fixed-sized stack (saved_regions and saved_buckets), when the
-// recursion unwinds but before returning from the outer hook call we unwind
-// this stack and move the data from saved_regions and saved_buckets to its
-// permanent place in the RegionSet and "bucket_table" respectively,
-// which can cause more allocations and mmap-s and recursion and unwinding,
-// but the whole process ends eventually due to the fact that for the small
-// allocations we are doing LowLevelAlloc reuses one mmap call and parcels out
-// the memory it created to satisfy several of our allocation requests.
-//
-
-// ========================================================================= //
-
-#include <config.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#elif !defined(MAP_FAILED)
-#define MAP_FAILED -1 // the only thing we need from mman.h
-#endif
-#ifdef HAVE_PTHREAD
-#include <pthread.h> // for pthread_t, pthread_self()
-#endif
-#include <stddef.h>
-
-#include <algorithm>
-#include <set>
-
-#include "memory_region_map.h"
-
-#include "base/googleinit.h"
-#include "base/logging.h"
-#include "base/low_level_alloc.h"
-#include "malloc_hook-inl.h"
-
-#include <gperftools/stacktrace.h>
-#include <gperftools/malloc_hook.h>
-
-// MREMAP_FIXED is a linux extension. How it's used in this file,
-// setting it to 0 is equivalent to saying, "This feature isn't
-// supported", which is right.
-#ifndef MREMAP_FIXED
-# define MREMAP_FIXED 0
-#endif
-
-using std::max;
-
-// ========================================================================= //
-
-int MemoryRegionMap::client_count_ = 0;
-int MemoryRegionMap::max_stack_depth_ = 0;
-MemoryRegionMap::RegionSet* MemoryRegionMap::regions_ = NULL;
-LowLevelAlloc::Arena* MemoryRegionMap::arena_ = NULL;
-SpinLock MemoryRegionMap::lock_(SpinLock::LINKER_INITIALIZED);
-SpinLock MemoryRegionMap::owner_lock_( // ACQUIRED_AFTER(lock_)
- SpinLock::LINKER_INITIALIZED);
-int MemoryRegionMap::recursion_count_ = 0; // GUARDED_BY(owner_lock_)
-pthread_t MemoryRegionMap::lock_owner_tid_; // GUARDED_BY(owner_lock_)
-int64 MemoryRegionMap::map_size_ = 0;
-int64 MemoryRegionMap::unmap_size_ = 0;
-HeapProfileBucket** MemoryRegionMap::bucket_table_ = NULL; // GUARDED_BY(lock_)
-int MemoryRegionMap::num_buckets_ = 0; // GUARDED_BY(lock_)
-int MemoryRegionMap::saved_buckets_count_ = 0; // GUARDED_BY(lock_)
-HeapProfileBucket MemoryRegionMap::saved_buckets_[20]; // GUARDED_BY(lock_)
-
-// GUARDED_BY(lock_)
-const void* MemoryRegionMap::saved_buckets_keys_[20][kMaxStackDepth];
-
-// ========================================================================= //
-
-// Simple hook into execution of global object constructors,
-// so that we do not call pthread_self() when it does not yet work.
-static bool libpthread_initialized = false;
-REGISTER_MODULE_INITIALIZER(libpthread_initialized_setter,
- libpthread_initialized = true);
-
-static inline bool current_thread_is(pthread_t should_be) {
- // Before main() runs, there's only one thread, so we're always that thread
- if (!libpthread_initialized) return true;
- // this starts working only sometime well into global constructor execution:
- return pthread_equal(pthread_self(), should_be);
-}
-
-// ========================================================================= //
-
-// Constructor-less place-holder to store a RegionSet in.
-union MemoryRegionMap::RegionSetRep {
- char rep[sizeof(RegionSet)];
- void* align_it; // do not need a better alignment for 'rep' than this
- RegionSet* region_set() { return reinterpret_cast<RegionSet*>(rep); }
-};
-
-// The bytes where MemoryRegionMap::regions_ will point to.
-// We use RegionSetRep with noop c-tor so that global construction
-// does not interfere.
-static MemoryRegionMap::RegionSetRep regions_rep;
-
-// ========================================================================= //
-
-// Has InsertRegionLocked been called recursively
-// (or rather should we *not* use regions_ to record a hooked mmap).
-static bool recursive_insert = false;
-
-void MemoryRegionMap::Init(int max_stack_depth, bool use_buckets) {
- RAW_VLOG(10, "MemoryRegionMap Init");
- RAW_CHECK(max_stack_depth >= 0, "");
- // Make sure we don't overflow the memory in region stacks:
- RAW_CHECK(max_stack_depth <= kMaxStackDepth,
- "need to increase kMaxStackDepth?");
- Lock();
- client_count_ += 1;
- max_stack_depth_ = max(max_stack_depth_, max_stack_depth);
- if (client_count_ > 1) {
- // not first client: already did initialization-proper
- Unlock();
- RAW_VLOG(10, "MemoryRegionMap Init increment done");
- return;
- }
- // Set our hooks and make sure they were installed:
- RAW_CHECK(MallocHook::AddMmapHook(&MmapHook), "");
- RAW_CHECK(MallocHook::AddMremapHook(&MremapHook), "");
- RAW_CHECK(MallocHook::AddSbrkHook(&SbrkHook), "");
- RAW_CHECK(MallocHook::AddMunmapHook(&MunmapHook), "");
- // We need to set recursive_insert since the NewArena call itself
- // will already do some allocations with mmap which our hooks will catch
- // recursive_insert allows us to buffer info about these mmap calls.
- // Note that Init() can be (and is) sometimes called
- // already from within an mmap/sbrk hook.
- recursive_insert = true;
- arena_ = LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena());
- recursive_insert = false;
- HandleSavedRegionsLocked(&InsertRegionLocked); // flush the buffered ones
- // Can't instead use HandleSavedRegionsLocked(&DoInsertRegionLocked) before
- // recursive_insert = false; as InsertRegionLocked will also construct
- // regions_ on demand for us.
- if (use_buckets) {
- const int table_bytes = kHashTableSize * sizeof(*bucket_table_);
- recursive_insert = true;
- bucket_table_ = static_cast<HeapProfileBucket**>(
- MyAllocator::Allocate(table_bytes));
- recursive_insert = false;
- memset(bucket_table_, 0, table_bytes);
- num_buckets_ = 0;
- }
- Unlock();
- RAW_VLOG(10, "MemoryRegionMap Init done");
-}
-
-bool MemoryRegionMap::Shutdown() {
- RAW_VLOG(10, "MemoryRegionMap Shutdown");
- Lock();
- RAW_CHECK(client_count_ > 0, "");
- client_count_ -= 1;
- if (client_count_ != 0) { // not last client; need not really shutdown
- Unlock();
- RAW_VLOG(10, "MemoryRegionMap Shutdown decrement done");
- return true;
- }
- if (bucket_table_ != NULL) {
- for (int i = 0; i < kHashTableSize; i++) {
- for (HeapProfileBucket* curr = bucket_table_[i]; curr != 0; /**/) {
- HeapProfileBucket* bucket = curr;
- curr = curr->next;
- MyAllocator::Free(bucket->stack, 0);
- MyAllocator::Free(bucket, 0);
- }
- }
- MyAllocator::Free(bucket_table_, 0);
- num_buckets_ = 0;
- bucket_table_ = NULL;
- }
- RAW_CHECK(MallocHook::RemoveMmapHook(&MmapHook), "");
- RAW_CHECK(MallocHook::RemoveMremapHook(&MremapHook), "");
- RAW_CHECK(MallocHook::RemoveSbrkHook(&SbrkHook), "");
- RAW_CHECK(MallocHook::RemoveMunmapHook(&MunmapHook), "");
- if (regions_) regions_->~RegionSet();
- regions_ = NULL;
- bool deleted_arena = LowLevelAlloc::DeleteArena(arena_);
- if (deleted_arena) {
- arena_ = 0;
- } else {
- RAW_LOG(WARNING, "Can't delete LowLevelAlloc arena: it's being used");
- }
- Unlock();
- RAW_VLOG(10, "MemoryRegionMap Shutdown done");
- return deleted_arena;
-}
-
-bool MemoryRegionMap::IsRecordingLocked() {
- RAW_CHECK(LockIsHeld(), "should be held (by this thread)");
- return client_count_ > 0;
-}
-
-// Invariants (once libpthread_initialized is true):
-// * While lock_ is not held, recursion_count_ is 0 (and
-// lock_owner_tid_ is the previous owner, but we don't rely on
-// that).
-// * recursion_count_ and lock_owner_tid_ are only written while
-// both lock_ and owner_lock_ are held. They may be read under
-// just owner_lock_.
-// * At entry and exit of Lock() and Unlock(), the current thread
-// owns lock_ iff pthread_equal(lock_owner_tid_, pthread_self())
-// && recursion_count_ > 0.
-void MemoryRegionMap::Lock() {
- {
- SpinLockHolder l(&owner_lock_);
- if (recursion_count_ > 0 && current_thread_is(lock_owner_tid_)) {
- RAW_CHECK(lock_.IsHeld(), "Invariants violated");
- recursion_count_++;
- RAW_CHECK(recursion_count_ <= 5,
- "recursive lock nesting unexpectedly deep");
- return;
- }
- }
- lock_.Lock();
- {
- SpinLockHolder l(&owner_lock_);
- RAW_CHECK(recursion_count_ == 0,
- "Last Unlock didn't reset recursion_count_");
- if (libpthread_initialized)
- lock_owner_tid_ = pthread_self();
- recursion_count_ = 1;
- }
-}
-
-void MemoryRegionMap::Unlock() {
- SpinLockHolder l(&owner_lock_);
- RAW_CHECK(recursion_count_ > 0, "unlock when not held");
- RAW_CHECK(lock_.IsHeld(),
- "unlock when not held, and recursion_count_ is wrong");
- RAW_CHECK(current_thread_is(lock_owner_tid_), "unlock by non-holder");
- recursion_count_--;
- if (recursion_count_ == 0) {
- lock_.Unlock();
- }
-}
-
-bool MemoryRegionMap::LockIsHeld() {
- SpinLockHolder l(&owner_lock_);
- return lock_.IsHeld() && current_thread_is(lock_owner_tid_);
-}
-
-const MemoryRegionMap::Region*
-MemoryRegionMap::DoFindRegionLocked(uintptr_t addr) {
- RAW_CHECK(LockIsHeld(), "should be held (by this thread)");
- if (regions_ != NULL) {
- Region sample;
- sample.SetRegionSetKey(addr);
- RegionSet::iterator region = regions_->lower_bound(sample);
- if (region != regions_->end()) {
- RAW_CHECK(addr <= region->end_addr, "");
- if (region->start_addr <= addr && addr < region->end_addr) {
- return &(*region);
- }
- }
- }
- return NULL;
-}
-
-bool MemoryRegionMap::FindRegion(uintptr_t addr, Region* result) {
- Lock();
- const Region* region = DoFindRegionLocked(addr);
- if (region != NULL) *result = *region; // create it as an independent copy
- Unlock();
- return region != NULL;
-}
-
-bool MemoryRegionMap::FindAndMarkStackRegion(uintptr_t stack_top,
- Region* result) {
- Lock();
- const Region* region = DoFindRegionLocked(stack_top);
- if (region != NULL) {
- RAW_VLOG(10, "Stack at %p is inside region %p..%p",
- reinterpret_cast<void*>(stack_top),
- reinterpret_cast<void*>(region->start_addr),
- reinterpret_cast<void*>(region->end_addr));
- const_cast<Region*>(region)->set_is_stack(); // now we know
- // cast is safe (set_is_stack does not change the set ordering key)
- *result = *region; // create *result as an independent copy
- }
- Unlock();
- return region != NULL;
-}
-
-HeapProfileBucket* MemoryRegionMap::GetBucket(int depth,
- const void* const key[]) {
- RAW_CHECK(LockIsHeld(), "should be held (by this thread)");
- // Make hash-value
- uintptr_t hash = 0;
- for (int i = 0; i < depth; i++) {
- hash += reinterpret_cast<uintptr_t>(key[i]);
- hash += hash << 10;
- hash ^= hash >> 6;
- }
- hash += hash << 3;
- hash ^= hash >> 11;
-
- // Lookup stack trace in table
- unsigned int hash_index = (static_cast<unsigned int>(hash)) % kHashTableSize;
- for (HeapProfileBucket* bucket = bucket_table_[hash_index];
- bucket != 0;
- bucket = bucket->next) {
- if ((bucket->hash == hash) && (bucket->depth == depth) &&
- std::equal(key, key + depth, bucket->stack)) {
- return bucket;
- }
- }
-
- // Create new bucket
- const size_t key_size = sizeof(key[0]) * depth;
- HeapProfileBucket* bucket;
- if (recursive_insert) { // recursion: save in saved_buckets_
- const void** key_copy = saved_buckets_keys_[saved_buckets_count_];
- std::copy(key, key + depth, key_copy);
- bucket = &saved_buckets_[saved_buckets_count_];
- memset(bucket, 0, sizeof(*bucket));
- ++saved_buckets_count_;
- bucket->stack = key_copy;
- bucket->next = NULL;
- } else {
- recursive_insert = true;
- const void** key_copy = static_cast<const void**>(
- MyAllocator::Allocate(key_size));
- recursive_insert = false;
- std::copy(key, key + depth, key_copy);
- recursive_insert = true;
- bucket = static_cast<HeapProfileBucket*>(
- MyAllocator::Allocate(sizeof(HeapProfileBucket)));
- recursive_insert = false;
- memset(bucket, 0, sizeof(*bucket));
- bucket->stack = key_copy;
- bucket->next = bucket_table_[hash_index];
- }
- bucket->hash = hash;
- bucket->depth = depth;
- bucket_table_[hash_index] = bucket;
- ++num_buckets_;
- return bucket;
-}
-
-MemoryRegionMap::RegionIterator MemoryRegionMap::BeginRegionLocked() {
- RAW_CHECK(LockIsHeld(), "should be held (by this thread)");
- RAW_CHECK(regions_ != NULL, "");
- return regions_->begin();
-}
-
-MemoryRegionMap::RegionIterator MemoryRegionMap::EndRegionLocked() {
- RAW_CHECK(LockIsHeld(), "should be held (by this thread)");
- RAW_CHECK(regions_ != NULL, "");
- return regions_->end();
-}
-
-inline void MemoryRegionMap::DoInsertRegionLocked(const Region& region) {
- RAW_VLOG(12, "Inserting region %p..%p from %p",
- reinterpret_cast<void*>(region.start_addr),
- reinterpret_cast<void*>(region.end_addr),
- reinterpret_cast<void*>(region.caller()));
- RegionSet::const_iterator i = regions_->lower_bound(region);
- if (i != regions_->end() && i->start_addr <= region.start_addr) {
- RAW_DCHECK(region.end_addr <= i->end_addr, ""); // lower_bound ensures this
- return; // 'region' is a subset of an already recorded region; do nothing
- // We can be stricter and allow this only when *i has been created via
- // an mmap with MAP_NORESERVE flag set.
- }
- if (DEBUG_MODE) {
- RAW_CHECK(i == regions_->end() || !region.Overlaps(*i),
- "Wow, overlapping memory regions");
- Region sample;
- sample.SetRegionSetKey(region.start_addr);
- i = regions_->lower_bound(sample);
- RAW_CHECK(i == regions_->end() || !region.Overlaps(*i),
- "Wow, overlapping memory regions");
- }
- region.AssertIsConsistent(); // just making sure
- // This inserts and allocates permanent storage for region
- // and its call stack data: it's safe to do it now:
- regions_->insert(region);
- RAW_VLOG(12, "Inserted region %p..%p :",
- reinterpret_cast<void*>(region.start_addr),
- reinterpret_cast<void*>(region.end_addr));
- if (VLOG_IS_ON(12)) LogAllLocked();
-}
-
-// These variables are local to MemoryRegionMap::InsertRegionLocked()
-// and MemoryRegionMap::HandleSavedRegionsLocked()
-// and are file-level to ensure that they are initialized at load time.
-
-// Number of unprocessed region inserts.
-static int saved_regions_count = 0;
-
-// Unprocessed inserts (must be big enough to hold all allocations that can
-// be caused by a InsertRegionLocked call).
-// Region has no constructor, so that c-tor execution does not interfere
-// with the any-time use of the static memory behind saved_regions.
-static MemoryRegionMap::Region saved_regions[20];
-
-inline void MemoryRegionMap::HandleSavedRegionsLocked(
- void (*insert_func)(const Region& region)) {
- while (saved_regions_count > 0) {
- // Making a local-var copy of the region argument to insert_func
- // including its stack (w/o doing any memory allocations) is important:
- // in many cases the memory in saved_regions
- // will get written-to during the (*insert_func)(r) call below.
- Region r = saved_regions[--saved_regions_count];
- (*insert_func)(r);
- }
-}
-
-void MemoryRegionMap::RestoreSavedBucketsLocked() {
- RAW_CHECK(LockIsHeld(), "should be held (by this thread)");
- while (saved_buckets_count_ > 0) {
- HeapProfileBucket bucket = saved_buckets_[--saved_buckets_count_];
- unsigned int hash_index =
- static_cast<unsigned int>(bucket.hash) % kHashTableSize;
- bool is_found = false;
- for (HeapProfileBucket* curr = bucket_table_[hash_index];
- curr != 0;
- curr = curr->next) {
- if ((curr->hash == bucket.hash) && (curr->depth == bucket.depth) &&
- std::equal(bucket.stack, bucket.stack + bucket.depth, curr->stack)) {
- curr->allocs += bucket.allocs;
- curr->alloc_size += bucket.alloc_size;
- curr->frees += bucket.frees;
- curr->free_size += bucket.free_size;
- is_found = true;
- break;
- }
- }
- if (is_found) continue;
-
- const size_t key_size = sizeof(bucket.stack[0]) * bucket.depth;
- const void** key_copy = static_cast<const void**>(
- MyAllocator::Allocate(key_size));
- std::copy(bucket.stack, bucket.stack + bucket.depth, key_copy);
- HeapProfileBucket* new_bucket = static_cast<HeapProfileBucket*>(
- MyAllocator::Allocate(sizeof(HeapProfileBucket)));
- memset(new_bucket, 0, sizeof(*new_bucket));
- new_bucket->hash = bucket.hash;
- new_bucket->depth = bucket.depth;
- new_bucket->stack = key_copy;
- new_bucket->next = bucket_table_[hash_index];
- bucket_table_[hash_index] = new_bucket;
- ++num_buckets_;
- }
-}
-
-inline void MemoryRegionMap::InsertRegionLocked(const Region& region) {
- RAW_CHECK(LockIsHeld(), "should be held (by this thread)");
- // We can be called recursively, because RegionSet constructor
- // and DoInsertRegionLocked() (called below) can call the allocator.
- // recursive_insert tells us if that's the case. When this happens,
- // region insertion information is recorded in saved_regions[],
- // and taken into account when the recursion unwinds.
- // Do the insert:
- if (recursive_insert) { // recursion: save in saved_regions
- RAW_VLOG(12, "Saving recursive insert of region %p..%p from %p",
- reinterpret_cast<void*>(region.start_addr),
- reinterpret_cast<void*>(region.end_addr),
- reinterpret_cast<void*>(region.caller()));
- RAW_CHECK(saved_regions_count < arraysize(saved_regions), "");
- // Copy 'region' to saved_regions[saved_regions_count]
- // together with the contents of its call_stack,
- // then increment saved_regions_count.
- saved_regions[saved_regions_count++] = region;
- } else { // not a recusrive call
- if (regions_ == NULL) { // init regions_
- RAW_VLOG(12, "Initializing region set");
- regions_ = regions_rep.region_set();
- recursive_insert = true;
- new(regions_) RegionSet();
- HandleSavedRegionsLocked(&DoInsertRegionLocked);
- recursive_insert = false;
- }
- recursive_insert = true;
- // Do the actual insertion work to put new regions into regions_:
- DoInsertRegionLocked(region);
- HandleSavedRegionsLocked(&DoInsertRegionLocked);
- recursive_insert = false;
- }
-}
-
-// We strip out different number of stack frames in debug mode
-// because less inlining happens in that case
-#ifdef NDEBUG
-static const int kStripFrames = 1;
-#else
-static const int kStripFrames = 3;
-#endif
-
-void MemoryRegionMap::RecordRegionAddition(const void* start, size_t size) {
- // Record start/end info about this memory acquisition call in a new region:
- Region region;
- region.Create(start, size);
- // First get the call stack info into the local varible 'region':
- int depth = 0;
- // NOTE: libunwind also does mmap and very much likely while holding
- // it's own lock(s). So some threads may first take libunwind lock,
- // and then take region map lock (necessary to record mmap done from
- // inside libunwind). On the other hand other thread(s) may do
- // normal mmap. Which would call this method to record it. Which
- // would then proceed with installing that record to region map
- // while holding region map lock. That may cause mmap from our own
- // internal allocators, so attempt to unwind in this case may cause
- // reverse order of taking libuwind and region map locks. Which is
- // obvious deadlock.
- //
- // Thankfully, we can easily detect if we're holding region map lock
- // and avoid recording backtrace in this (rare and largely
- // irrelevant) case. By doing this we "declare" that thread needing
- // both locks must take region map lock last. In other words we do
- // not allow taking libuwind lock when we already have region map
- // lock. Note, this is generally impossible when somebody tries to
- // mix cpu profiling and heap checking/profiling, because cpu
- // profiler grabs backtraces at arbitrary places. But at least such
- // combination is rarer and less relevant.
- if (max_stack_depth_ > 0 && !LockIsHeld()) {
- depth = MallocHook::GetCallerStackTrace(const_cast<void**>(region.call_stack),
- max_stack_depth_, kStripFrames + 1);
- }
- region.set_call_stack_depth(depth); // record stack info fully
- RAW_VLOG(10, "New global region %p..%p from %p",
- reinterpret_cast<void*>(region.start_addr),
- reinterpret_cast<void*>(region.end_addr),
- reinterpret_cast<void*>(region.caller()));
- // Note: none of the above allocates memory.
- Lock(); // recursively lock
- map_size_ += size;
- InsertRegionLocked(region);
- // This will (eventually) allocate storage for and copy over the stack data
- // from region.call_stack_data_ that is pointed by region.call_stack().
- if (bucket_table_ != NULL) {
- HeapProfileBucket* b = GetBucket(depth, region.call_stack);
- ++b->allocs;
- b->alloc_size += size;
- if (!recursive_insert) {
- recursive_insert = true;
- RestoreSavedBucketsLocked();
- recursive_insert = false;
- }
- }
- Unlock();
-}
-
-void MemoryRegionMap::RecordRegionRemoval(const void* start, size_t size) {
- Lock();
- if (recursive_insert) {
- // First remove the removed region from saved_regions, if it's
- // there, to prevent overrunning saved_regions in recursive
- // map/unmap call sequences, and also from later inserting regions
- // which have already been unmapped.
- uintptr_t start_addr = reinterpret_cast<uintptr_t>(start);
- uintptr_t end_addr = start_addr + size;
- int put_pos = 0;
- int old_count = saved_regions_count;
- for (int i = 0; i < old_count; ++i, ++put_pos) {
- Region& r = saved_regions[i];
- if (r.start_addr == start_addr && r.end_addr == end_addr) {
- // An exact match, so it's safe to remove.
- RecordRegionRemovalInBucket(r.call_stack_depth, r.call_stack, size);
- --saved_regions_count;
- --put_pos;
- RAW_VLOG(10, ("Insta-Removing saved region %p..%p; "
- "now have %d saved regions"),
- reinterpret_cast<void*>(start_addr),
- reinterpret_cast<void*>(end_addr),
- saved_regions_count);
- } else {
- if (put_pos < i) {
- saved_regions[put_pos] = saved_regions[i];
- }
- }
- }
- }
- if (regions_ == NULL) { // We must have just unset the hooks,
- // but this thread was already inside the hook.
- Unlock();
- return;
- }
- if (!recursive_insert) {
- HandleSavedRegionsLocked(&InsertRegionLocked);
- }
- // first handle adding saved regions if any
- uintptr_t start_addr = reinterpret_cast<uintptr_t>(start);
- uintptr_t end_addr = start_addr + size;
- // subtract start_addr, end_addr from all the regions
- RAW_VLOG(10, "Removing global region %p..%p; have %" PRIuS " regions",
- reinterpret_cast<void*>(start_addr),
- reinterpret_cast<void*>(end_addr),
- regions_->size());
- Region sample;
- sample.SetRegionSetKey(start_addr);
- // Only iterate over the regions that might overlap start_addr..end_addr:
- for (RegionSet::iterator region = regions_->lower_bound(sample);
- region != regions_->end() && region->start_addr < end_addr;
- /*noop*/) {
- RAW_VLOG(13, "Looking at region %p..%p",
- reinterpret_cast<void*>(region->start_addr),
- reinterpret_cast<void*>(region->end_addr));
- if (start_addr <= region->start_addr &&
- region->end_addr <= end_addr) { // full deletion
- RAW_VLOG(12, "Deleting region %p..%p",
- reinterpret_cast<void*>(region->start_addr),
- reinterpret_cast<void*>(region->end_addr));
- RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack,
- region->end_addr - region->start_addr);
- RegionSet::iterator d = region;
- ++region;
- regions_->erase(d);
- continue;
- } else if (region->start_addr < start_addr &&
- end_addr < region->end_addr) { // cutting-out split
- RAW_VLOG(12, "Splitting region %p..%p in two",
- reinterpret_cast<void*>(region->start_addr),
- reinterpret_cast<void*>(region->end_addr));
- RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack,
- end_addr - start_addr);
- // Make another region for the start portion:
- // The new region has to be the start portion because we can't
- // just modify region->end_addr as it's the sorting key.
- Region r = *region;
- r.set_end_addr(start_addr);
- InsertRegionLocked(r);
- // cut *region from start:
- const_cast<Region&>(*region).set_start_addr(end_addr);
- } else if (end_addr > region->start_addr &&
- start_addr <= region->start_addr) { // cut from start
- RAW_VLOG(12, "Start-chopping region %p..%p",
- reinterpret_cast<void*>(region->start_addr),
- reinterpret_cast<void*>(region->end_addr));
- RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack,
- end_addr - region->start_addr);
- const_cast<Region&>(*region).set_start_addr(end_addr);
- } else if (start_addr > region->start_addr &&
- start_addr < region->end_addr) { // cut from end
- RAW_VLOG(12, "End-chopping region %p..%p",
- reinterpret_cast<void*>(region->start_addr),
- reinterpret_cast<void*>(region->end_addr));
- RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack,
- region->end_addr - start_addr);
- // Can't just modify region->end_addr (it's the sorting key):
- Region r = *region;
- r.set_end_addr(start_addr);
- RegionSet::iterator d = region;
- ++region;
- // It's safe to erase before inserting since r is independent of *d:
- // r contains an own copy of the call stack:
- regions_->erase(d);
- InsertRegionLocked(r);
- continue;
- }
- ++region;
- }
- RAW_VLOG(12, "Removed region %p..%p; have %" PRIuS " regions",
- reinterpret_cast<void*>(start_addr),
- reinterpret_cast<void*>(end_addr),
- regions_->size());
- if (VLOG_IS_ON(12)) LogAllLocked();
- unmap_size_ += size;
- Unlock();
-}
-
-void MemoryRegionMap::RecordRegionRemovalInBucket(int depth,
- const void* const stack[],
- size_t size) {
- RAW_CHECK(LockIsHeld(), "should be held (by this thread)");
- if (bucket_table_ == NULL) return;
- HeapProfileBucket* b = GetBucket(depth, stack);
- ++b->frees;
- b->free_size += size;
-}
-
-void MemoryRegionMap::MmapHook(const void* result,
- const void* start, size_t size,
- int prot, int flags,
- 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 %" 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));
- if (result != reinterpret_cast<void*>(MAP_FAILED) && size != 0) {
- RecordRegionAddition(result, size);
- }
-}
-
-void MemoryRegionMap::MunmapHook(const void* ptr, size_t size) {
- RAW_VLOG(10, "MUnmap of %p %" PRIuS "", ptr, size);
- if (size != 0) {
- RecordRegionRemoval(ptr, size);
- }
-}
-
-void MemoryRegionMap::MremapHook(const void* result,
- const void* old_addr, size_t old_size,
- size_t new_size, int flags,
- const void* new_addr) {
- RAW_VLOG(10, "MRemap = 0x%" PRIxPTR " of 0x%" PRIxPTR " %" PRIuS " "
- "to %" PRIuS " flags %d new_addr=0x%" PRIxPTR,
- (uintptr_t)result, (uintptr_t)old_addr,
- old_size, new_size, flags,
- flags & MREMAP_FIXED ? (uintptr_t)new_addr : 0);
- if (result != reinterpret_cast<void*>(-1)) {
- RecordRegionRemoval(old_addr, old_size);
- RecordRegionAddition(result, new_size);
- }
-}
-
-void MemoryRegionMap::SbrkHook(const void* result, ptrdiff_t increment) {
- RAW_VLOG(10, "Sbrk = 0x%" PRIxPTR " of %" PRIdS "", (uintptr_t)result, increment);
- if (result != reinterpret_cast<void*>(-1)) {
- if (increment > 0) {
- void* new_end = sbrk(0);
- RecordRegionAddition(result, reinterpret_cast<uintptr_t>(new_end) -
- reinterpret_cast<uintptr_t>(result));
- } else if (increment < 0) {
- void* new_end = sbrk(0);
- RecordRegionRemoval(new_end, reinterpret_cast<uintptr_t>(result) -
- reinterpret_cast<uintptr_t>(new_end));
- }
- }
-}
-
-void MemoryRegionMap::LogAllLocked() {
- RAW_CHECK(LockIsHeld(), "should be held (by this thread)");
- RAW_LOG(INFO, "List of regions:");
- uintptr_t previous = 0;
- for (RegionSet::const_iterator r = regions_->begin();
- r != regions_->end(); ++r) {
- RAW_LOG(INFO, "Memory region 0x%" PRIxPTR "..0x%" PRIxPTR " "
- "from 0x%" PRIxPTR " stack=%d",
- r->start_addr, r->end_addr, r->caller(), r->is_stack);
- RAW_CHECK(previous < r->end_addr, "wow, we messed up the set order");
- // this must be caused by uncontrolled recursive operations on regions_
- previous = r->end_addr;
- }
- RAW_LOG(INFO, "End of regions list");
-}
diff --git a/src/third_party/gperftools-2.5/src/memory_region_map.h b/src/third_party/gperftools-2.5/src/memory_region_map.h
deleted file mode 100644
index ec388e1cc54..00000000000
--- a/src/third_party/gperftools-2.5/src/memory_region_map.h
+++ /dev/null
@@ -1,413 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2006, 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: Maxim Lifantsev
- */
-
-#ifndef BASE_MEMORY_REGION_MAP_H_
-#define BASE_MEMORY_REGION_MAP_H_
-
-#include <config.h>
-
-#ifdef HAVE_PTHREAD
-#include <pthread.h>
-#endif
-#include <stddef.h>
-#include <set>
-#include "base/stl_allocator.h"
-#include "base/spinlock.h"
-#include "base/thread_annotations.h"
-#include "base/low_level_alloc.h"
-#include "heap-profile-stats.h"
-
-// TODO(maxim): add a unittest:
-// execute a bunch of mmaps and compare memory map what strace logs
-// execute a bunch of mmap/munmup and compare memory map with
-// own accounting of what those mmaps generated
-
-// Thread-safe class to collect and query the map of all memory regions
-// in a process that have been created with mmap, munmap, mremap, sbrk.
-// For each memory region, we keep track of (and provide to users)
-// the stack trace that allocated that memory region.
-// The recorded stack trace depth is bounded by
-// a user-supplied max_stack_depth parameter of Init().
-// After initialization with Init()
-// (which can happened even before global object constructor execution)
-// we collect the map by installing and monitoring MallocHook-s
-// to mmap, munmap, mremap, sbrk.
-// At any time one can query this map via provided interface.
-// For more details on the design of MemoryRegionMap
-// see the comment at the top of our .cc file.
-class MemoryRegionMap {
- private:
- // Max call stack recording depth supported by Init(). Set it to be
- // high enough for all our clients. Note: we do not define storage
- // for this (doing that requires special handling in windows), so
- // don't take the address of it!
- static const int kMaxStackDepth = 32;
-
- // Size of the hash table of buckets. A structure of the bucket table is
- // described in heap-profile-stats.h.
- static const int kHashTableSize = 179999;
-
- public:
- // interface ================================================================
-
- // Every client of MemoryRegionMap must call Init() before first use,
- // and Shutdown() after last use. This allows us to reference count
- // this (singleton) class properly. MemoryRegionMap assumes it's the
- // only client of MallocHooks, so a client can only register other
- // MallocHooks after calling Init() and must unregister them before
- // calling Shutdown().
-
- // Initialize this module to record memory allocation stack traces.
- // Stack traces that have more than "max_stack_depth" frames
- // are automatically shrunk to "max_stack_depth" when they are recorded.
- // Init() can be called more than once w/o harm, largest max_stack_depth
- // will be the effective one.
- // When "use_buckets" is true, then counts of mmap and munmap sizes will be
- // recorded with each stack trace. If Init() is called more than once, then
- // counting will be effective after any call contained "use_buckets" of true.
- // It will install mmap, munmap, mremap, sbrk hooks
- // and initialize arena_ and our hook and locks, hence one can use
- // MemoryRegionMap::Lock()/Unlock() to manage the locks.
- // Uses Lock/Unlock inside.
- static void Init(int max_stack_depth, bool use_buckets);
-
- // Try to shutdown this module undoing what Init() did.
- // Returns true iff could do full shutdown (or it was not attempted).
- // Full shutdown is attempted when the number of Shutdown() calls equals
- // the number of Init() calls.
- static bool Shutdown();
-
- // Return true if MemoryRegionMap is initialized and recording, i.e. when
- // then number of Init() calls are more than the number of Shutdown() calls.
- static bool IsRecordingLocked();
-
- // Locks to protect our internal data structures.
- // These also protect use of arena_ if our Init() has been done.
- // The lock is recursive.
- static void Lock() EXCLUSIVE_LOCK_FUNCTION(lock_);
- static void Unlock() UNLOCK_FUNCTION(lock_);
-
- // Returns true when the lock is held by this thread (for use in RAW_CHECK-s).
- static bool LockIsHeld();
-
- // Locker object that acquires the MemoryRegionMap::Lock
- // for the duration of its lifetime (a C++ scope).
- class LockHolder {
- public:
- LockHolder() { Lock(); }
- ~LockHolder() { Unlock(); }
- private:
- DISALLOW_COPY_AND_ASSIGN(LockHolder);
- };
-
- // A memory region that we know about through malloc_hook-s.
- // This is essentially an interface through which MemoryRegionMap
- // exports the collected data to its clients. Thread-compatible.
- struct Region {
- uintptr_t start_addr; // region start address
- uintptr_t end_addr; // region end address
- int call_stack_depth; // number of caller stack frames that we saved
- const void* call_stack[kMaxStackDepth]; // caller address stack array
- // filled to call_stack_depth size
- bool is_stack; // does this region contain a thread's stack:
- // a user of MemoryRegionMap supplies this info
-
- // Convenience accessor for call_stack[0],
- // i.e. (the program counter of) the immediate caller
- // of this region's allocation function,
- // but it also returns NULL when call_stack_depth is 0,
- // i.e whe we weren't able to get the call stack.
- // This usually happens in recursive calls, when the stack-unwinder
- // calls mmap() which in turn calls the stack-unwinder.
- uintptr_t caller() const {
- return reinterpret_cast<uintptr_t>(call_stack_depth >= 1
- ? call_stack[0] : NULL);
- }
-
- // Return true iff this region overlaps region x.
- bool Overlaps(const Region& x) const {
- return start_addr < x.end_addr && end_addr > x.start_addr;
- }
-
- private: // helpers for MemoryRegionMap
- friend class MemoryRegionMap;
-
- // The ways we create Region-s:
- void Create(const void* start, size_t size) {
- start_addr = reinterpret_cast<uintptr_t>(start);
- end_addr = start_addr + size;
- is_stack = false; // not a stack till marked such
- call_stack_depth = 0;
- AssertIsConsistent();
- }
- void set_call_stack_depth(int depth) {
- RAW_DCHECK(call_stack_depth == 0, ""); // only one such set is allowed
- call_stack_depth = depth;
- AssertIsConsistent();
- }
-
- // The ways we modify Region-s:
- void set_is_stack() { is_stack = true; }
- void set_start_addr(uintptr_t addr) {
- start_addr = addr;
- AssertIsConsistent();
- }
- void set_end_addr(uintptr_t addr) {
- end_addr = addr;
- AssertIsConsistent();
- }
-
- // Verifies that *this contains consistent data, crashes if not the case.
- void AssertIsConsistent() const {
- RAW_DCHECK(start_addr < end_addr, "");
- RAW_DCHECK(call_stack_depth >= 0 &&
- call_stack_depth <= kMaxStackDepth, "");
- }
-
- // Post-default construction helper to make a Region suitable
- // for searching in RegionSet regions_.
- void SetRegionSetKey(uintptr_t addr) {
- // make sure *this has no usable data:
- if (DEBUG_MODE) memset(this, 0xFF, sizeof(*this));
- end_addr = addr;
- }
-
- // Note: call_stack[kMaxStackDepth] as a member lets us make Region
- // a simple self-contained struct with correctly behaving bit-vise copying.
- // This simplifies the code of this module but wastes some memory:
- // in most-often use case of this module (leak checking)
- // only one call_stack element out of kMaxStackDepth is actually needed.
- // Making the storage for call_stack variable-sized,
- // substantially complicates memory management for the Region-s:
- // as they need to be created and manipulated for some time
- // w/o any memory allocations, yet are also given out to the users.
- };
-
- // Find the region that covers addr and write its data into *result if found,
- // in which case *result gets filled so that it stays fully functional
- // even when the underlying region gets removed from MemoryRegionMap.
- // Returns success. Uses Lock/Unlock inside.
- static bool FindRegion(uintptr_t addr, Region* result);
-
- // Find the region that contains stack_top, mark that region as
- // a stack region, and write its data into *result if found,
- // in which case *result gets filled so that it stays fully functional
- // even when the underlying region gets removed from MemoryRegionMap.
- // Returns success. Uses Lock/Unlock inside.
- static bool FindAndMarkStackRegion(uintptr_t stack_top, Region* result);
-
- // Iterate over the buckets which store mmap and munmap counts per stack
- // trace. It calls "callback" for each bucket, and passes "arg" to it.
- template<class Type>
- static void IterateBuckets(void (*callback)(const HeapProfileBucket*, Type),
- Type arg);
-
- // Get the bucket whose caller stack trace is "key". The stack trace is
- // used to a depth of "depth" at most. The requested bucket is created if
- // needed.
- // The bucket table is described in heap-profile-stats.h.
- static HeapProfileBucket* GetBucket(int depth, const void* const key[]);
-
- private: // our internal types ==============================================
-
- // Region comparator for sorting with STL
- struct RegionCmp {
- bool operator()(const Region& x, const Region& y) const {
- return x.end_addr < y.end_addr;
- }
- };
-
- // We allocate STL objects in our own arena.
- struct MyAllocator {
- static void *Allocate(size_t n) {
- return LowLevelAlloc::AllocWithArena(n, arena_);
- }
- static void Free(const void *p, size_t /* n */) {
- LowLevelAlloc::Free(const_cast<void*>(p));
- }
- };
-
- // Set of the memory regions
- typedef std::set<Region, RegionCmp,
- STL_Allocator<Region, MyAllocator> > RegionSet;
-
- public: // more in-depth interface ==========================================
-
- // STL iterator with values of Region
- typedef RegionSet::const_iterator RegionIterator;
-
- // Return the begin/end iterators to all the regions.
- // These need Lock/Unlock protection around their whole usage (loop).
- // Even when the same thread causes modifications during such a loop
- // (which are permitted due to recursive locking)
- // the loop iterator will still be valid as long as its region
- // has not been deleted, but EndRegionLocked should be
- // re-evaluated whenever the set of regions has changed.
- static RegionIterator BeginRegionLocked();
- static RegionIterator EndRegionLocked();
-
- // Return the accumulated sizes of mapped and unmapped regions.
- static int64 MapSize() { return map_size_; }
- static int64 UnmapSize() { return unmap_size_; }
-
- // Effectively private type from our .cc =================================
- // public to let us declare global objects:
- union RegionSetRep;
-
- private:
- // representation ===========================================================
-
- // Counter of clients of this module that have called Init().
- static int client_count_;
-
- // Maximal number of caller stack frames to save (>= 0).
- static int max_stack_depth_;
-
- // Arena used for our allocations in regions_.
- static LowLevelAlloc::Arena* arena_;
-
- // Set of the mmap/sbrk/mremap-ed memory regions
- // To be accessed *only* when Lock() is held.
- // Hence we protect the non-recursive lock used inside of arena_
- // with our recursive Lock(). This lets a user prevent deadlocks
- // when threads are stopped by TCMalloc_ListAllProcessThreads at random spots
- // simply by acquiring our recursive Lock() before that.
- static RegionSet* regions_;
-
- // Lock to protect regions_ and buckets_ variables and the data behind.
- static SpinLock lock_;
- // Lock to protect the recursive lock itself.
- static SpinLock owner_lock_;
-
- // Recursion count for the recursive lock.
- static int recursion_count_;
- // The thread id of the thread that's inside the recursive lock.
- static pthread_t lock_owner_tid_;
-
- // Total size of all mapped pages so far
- static int64 map_size_;
- // Total size of all unmapped pages so far
- static int64 unmap_size_;
-
- // Bucket hash table which is described in heap-profile-stats.h.
- static HeapProfileBucket** bucket_table_ GUARDED_BY(lock_);
- static int num_buckets_ GUARDED_BY(lock_);
-
- // The following members are local to MemoryRegionMap::GetBucket()
- // and MemoryRegionMap::HandleSavedBucketsLocked()
- // and are file-level to ensure that they are initialized at load time.
- //
- // These are used as temporary storage to break the infinite cycle of mmap
- // calling our hook which (sometimes) causes mmap. It must be a static
- // fixed-size array. The size 20 is just an expected value for safety.
- // The details are described in memory_region_map.cc.
-
- // Number of unprocessed bucket inserts.
- static int saved_buckets_count_ GUARDED_BY(lock_);
-
- // Unprocessed inserts (must be big enough to hold all mmaps that can be
- // caused by a GetBucket call).
- // Bucket has no constructor, so that c-tor execution does not interfere
- // with the any-time use of the static memory behind saved_buckets.
- static HeapProfileBucket saved_buckets_[20] GUARDED_BY(lock_);
-
- static const void* saved_buckets_keys_[20][kMaxStackDepth] GUARDED_BY(lock_);
-
- // helpers ==================================================================
-
- // Helper for FindRegion and FindAndMarkStackRegion:
- // returns the region covering 'addr' or NULL; assumes our lock_ is held.
- static const Region* DoFindRegionLocked(uintptr_t addr);
-
- // Verifying wrapper around regions_->insert(region)
- // To be called to do InsertRegionLocked's work only!
- inline static void DoInsertRegionLocked(const Region& region);
- // Handle regions saved by InsertRegionLocked into a tmp static array
- // by calling insert_func on them.
- inline static void HandleSavedRegionsLocked(
- void (*insert_func)(const Region& region));
-
- // Restore buckets saved in a tmp static array by GetBucket to the bucket
- // table where all buckets eventually should be.
- static void RestoreSavedBucketsLocked();
-
- // Wrapper around DoInsertRegionLocked
- // that handles the case of recursive allocator calls.
- inline static void InsertRegionLocked(const Region& region);
-
- // Record addition of a memory region at address "start" of size "size"
- // (called from our mmap/mremap/sbrk hooks).
- static void RecordRegionAddition(const void* start, size_t size);
- // Record deletion of a memory region at address "start" of size "size"
- // (called from our munmap/mremap/sbrk hooks).
- static void RecordRegionRemoval(const void* start, size_t size);
-
- // Record deletion of a memory region of size "size" in a bucket whose
- // caller stack trace is "key". The stack trace is used to a depth of
- // "depth" at most.
- static void RecordRegionRemovalInBucket(int depth,
- const void* const key[],
- size_t size);
-
- // Hooks for MallocHook
- static void MmapHook(const void* result,
- const void* start, size_t size,
- int prot, int flags,
- int fd, off_t offset);
- static void MunmapHook(const void* ptr, size_t size);
- static void MremapHook(const void* result, const void* old_addr,
- size_t old_size, size_t new_size, int flags,
- const void* new_addr);
- static void SbrkHook(const void* result, ptrdiff_t increment);
-
- // Log all memory regions; Useful for debugging only.
- // Assumes Lock() is held
- static void LogAllLocked();
-
- DISALLOW_COPY_AND_ASSIGN(MemoryRegionMap);
-};
-
-template <class Type>
-void MemoryRegionMap::IterateBuckets(
- void (*callback)(const HeapProfileBucket*, Type), Type callback_arg) {
- for (int index = 0; index < kHashTableSize; index++) {
- for (HeapProfileBucket* bucket = bucket_table_[index];
- bucket != NULL;
- bucket = bucket->next) {
- callback(bucket, callback_arg);
- }
- }
-}
-
-#endif // BASE_MEMORY_REGION_MAP_H_
diff --git a/src/third_party/gperftools-2.5/src/packed-cache-inl.h b/src/third_party/gperftools-2.5/src/packed-cache-inl.h
deleted file mode 100644
index 09462608ece..00000000000
--- a/src/third_party/gperftools-2.5/src/packed-cache-inl.h
+++ /dev/null
@@ -1,239 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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: Geoff Pike
-//
-// This file provides a minimal cache that can hold a <key, value> pair
-// with little if any wasted space. The types of the key and value
-// must be unsigned integral types or at least have unsigned semantics
-// for >>, casting, and similar operations.
-//
-// Synchronization is not provided. However, the cache is implemented
-// as an array of cache entries whose type is chosen at compile time.
-// If a[i] is atomic on your hardware for the chosen array type then
-// raciness will not necessarily lead to bugginess. The cache entries
-// must be large enough to hold a partial key and a value packed
-// together. The partial keys are bit strings of length
-// kKeybits - kHashbits, and the values are bit strings of length kValuebits.
-//
-// In an effort to use minimal space, every cache entry represents
-// some <key, value> pair; the class provides no way to mark a cache
-// entry as empty or uninitialized. In practice, you may want to have
-// reserved keys or values to get around this limitation. For example, in
-// tcmalloc's PageID-to-sizeclass cache, a value of 0 is used as
-// "unknown sizeclass."
-//
-// Usage Considerations
-// --------------------
-//
-// kHashbits controls the size of the cache. The best value for
-// kHashbits will of course depend on the application. Perhaps try
-// tuning the value of kHashbits by measuring different values on your
-// favorite benchmark. Also remember not to be a pig; other
-// programs that need resources may suffer if you are.
-//
-// The main uses for this class will be when performance is
-// critical and there's a convenient type to hold the cache's
-// entries. As described above, the number of bits required
-// for a cache entry is (kKeybits - kHashbits) + kValuebits. Suppose
-// kKeybits + kValuebits is 43. Then it probably makes sense to
-// chose kHashbits >= 11 so that cache entries fit in a uint32.
-//
-// On the other hand, suppose kKeybits = kValuebits = 64. Then
-// using this class may be less worthwhile. You'll probably
-// be using 128 bits for each entry anyway, so maybe just pick
-// a hash function, H, and use an array indexed by H(key):
-// void Put(K key, V value) { a_[H(key)] = pair<K, V>(key, value); }
-// V GetOrDefault(K key, V default) { const pair<K, V> &p = a_[H(key)]; ... }
-// etc.
-//
-// Further Details
-// ---------------
-//
-// For caches used only by one thread, the following is true:
-// 1. For a cache c,
-// (c.Put(key, value), c.GetOrDefault(key, 0)) == value
-// and
-// (c.Put(key, value), <...>, c.GetOrDefault(key, 0)) == value
-// if the elided code contains no c.Put calls.
-//
-// 2. Has(key) will return false if no <key, value> pair with that key
-// has ever been Put. However, a newly initialized cache will have
-// some <key, value> pairs already present. When you create a new
-// cache, you must specify an "initial value." The initialization
-// procedure is equivalent to Clear(initial_value), which is
-// equivalent to Put(k, initial_value) for all keys k from 0 to
-// 2^kHashbits - 1.
-//
-// 3. If key and key' differ then the only way Put(key, value) may
-// cause Has(key') to change is that Has(key') may change from true to
-// false. Furthermore, a Put() call that doesn't change Has(key')
-// doesn't change GetOrDefault(key', ...) either.
-//
-// Implementation details:
-//
-// This is a direct-mapped cache with 2^kHashbits entries; the hash
-// function simply takes the low bits of the key. We store whole keys
-// if a whole key plus a whole value fits in an entry. Otherwise, an
-// entry is the high bits of a key and a value, packed together.
-// E.g., a 20 bit key and a 7 bit value only require a uint16 for each
-// entry if kHashbits >= 11.
-//
-// Alternatives to this scheme will be added as needed.
-
-#ifndef TCMALLOC_PACKED_CACHE_INL_H_
-#define TCMALLOC_PACKED_CACHE_INL_H_
-
-#include "config.h"
-#include <stddef.h> // for size_t
-#ifdef HAVE_STDINT_H
-#include <stdint.h> // for uintptr_t
-#endif
-#include "base/basictypes.h"
-#include "internal_logging.h"
-
-// A safe way of doing "(1 << n) - 1" -- without worrying about overflow
-// Note this will all be resolved to a constant expression at compile-time
-#define N_ONES_(IntType, N) \
- ( (N) == 0 ? 0 : ((static_cast<IntType>(1) << ((N)-1))-1 + \
- (static_cast<IntType>(1) << ((N)-1))) )
-
-// The types K and V provide upper bounds on the number of valid keys
-// and values, but we explicitly require the keys to be less than
-// 2^kKeybits and the values to be less than 2^kValuebits. The size of
-// the table is controlled by kHashbits, and the type of each entry in
-// the cache is T. See also the big comment at the top of the file.
-template <int kKeybits, typename T>
-class PackedCache {
- public:
- typedef uintptr_t K;
- typedef size_t V;
-#ifdef TCMALLOC_SMALL_BUT_SLOW
- // Decrease the size map cache if running in the small memory mode.
- static const int kHashbits = 12;
-#else
- static const int kHashbits = 16;
-#endif
- static const int kValuebits = 7;
- static const bool kUseWholeKeys = kKeybits + kValuebits <= 8 * sizeof(T);
-
- explicit PackedCache(V initial_value) {
- COMPILE_ASSERT(kKeybits <= sizeof(K) * 8, key_size);
- COMPILE_ASSERT(kValuebits <= sizeof(V) * 8, value_size);
- COMPILE_ASSERT(kHashbits <= kKeybits, hash_function);
- COMPILE_ASSERT(kKeybits - kHashbits + kValuebits <= kTbits,
- entry_size_must_be_big_enough);
- Clear(initial_value);
- }
-
- void Put(K key, V value) {
- ASSERT(key == (key & kKeyMask));
- ASSERT(value == (value & kValueMask));
- array_[Hash(key)] = KeyToUpper(key) | value;
- }
-
- bool Has(K key) const {
- ASSERT(key == (key & kKeyMask));
- return KeyMatch(array_[Hash(key)], key);
- }
-
- V GetOrDefault(K key, V default_value) const {
- // As with other code in this class, we touch array_ as few times
- // as we can. Assuming entries are read atomically (e.g., their
- // type is uintptr_t on most hardware) then certain races are
- // harmless.
- ASSERT(key == (key & kKeyMask));
- T entry = array_[Hash(key)];
- return KeyMatch(entry, key) ? EntryToValue(entry) : default_value;
- }
-
- void Clear(V value) {
- ASSERT(value == (value & kValueMask));
- for (int i = 0; i < 1 << kHashbits; i++) {
- ASSERT(kUseWholeKeys || KeyToUpper(i) == 0);
- array_[i] = kUseWholeKeys ? (value | KeyToUpper(i)) : value;
- }
- }
-
- private:
- // We are going to pack a value and the upper part of a key (or a
- // whole key) into an entry of type T. The UPPER type is for the
- // upper part of a key, after the key has been masked and shifted
- // for inclusion in an entry.
- typedef T UPPER;
-
- static V EntryToValue(T t) { return t & kValueMask; }
-
- // If we have space for a whole key, we just shift it left.
- // Otherwise kHashbits determines where in a K to find the upper
- // part of the key, and kValuebits determines where in the entry to
- // put it.
- static UPPER KeyToUpper(K k) {
- if (kUseWholeKeys) {
- return static_cast<T>(k) << kValuebits;
- } else {
- const int shift = kHashbits - kValuebits;
- // Assume kHashbits >= kValuebits. It'd be easy to lift this assumption.
- return static_cast<T>(k >> shift) & kUpperMask;
- }
- }
-
- static size_t Hash(K key) {
- return static_cast<size_t>(key) & N_ONES_(size_t, kHashbits);
- }
-
- // Does the entry match the relevant part of the given key?
- static bool KeyMatch(T entry, K key) {
- return kUseWholeKeys ?
- (entry >> kValuebits == key) :
- ((KeyToUpper(key) ^ entry) & kUpperMask) == 0;
- }
-
- static const int kTbits = 8 * sizeof(T);
- static const int kUpperbits = kUseWholeKeys ? kKeybits : kKeybits - kHashbits;
-
- // For masking a K.
- static const K kKeyMask = N_ONES_(K, kKeybits);
-
- // For masking a T.
- static const T kUpperMask = N_ONES_(T, kUpperbits) << kValuebits;
-
- // For masking a V or a T.
- static const V kValueMask = N_ONES_(V, kValuebits);
-
- // array_ is the cache. Its elements are volatile because any
- // thread can write any array element at any time.
- volatile T array_[1 << kHashbits];
-};
-
-#undef N_ONES_
-
-#endif // TCMALLOC_PACKED_CACHE_INL_H_
diff --git a/src/third_party/gperftools-2.5/src/page_heap.cc b/src/third_party/gperftools-2.5/src/page_heap.cc
deleted file mode 100644
index eaa33255f2c..00000000000
--- a/src/third_party/gperftools-2.5/src/page_heap.cc
+++ /dev/null
@@ -1,697 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-
-#include <config.h>
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h> // for PRIuPTR
-#endif
-#include <errno.h> // for ENOMEM, errno
-#include <gperftools/malloc_extension.h> // for MallocRange, etc
-#include "base/basictypes.h"
-#include "base/commandlineflags.h"
-#include "internal_logging.h" // for ASSERT, TCMalloc_Printer, etc
-#include "page_heap_allocator.h" // for PageHeapAllocator
-#include "static_vars.h" // for Static
-#include "system-alloc.h" // for TCMalloc_SystemAlloc, etc
-
-DEFINE_double(tcmalloc_release_rate,
- EnvToDouble("TCMALLOC_RELEASE_RATE", 1.0),
- "Rate at which we release unused memory to the system. "
- "Zero means we never release memory back to the system. "
- "Increase this flag to return memory faster; decrease it "
- "to return memory slower. Reasonable rates are in the "
- "range [0,10]");
-
-DEFINE_int64(tcmalloc_heap_limit_mb,
- EnvToInt("TCMALLOC_HEAP_LIMIT_MB", 0),
- "Limit total size of the process heap to the "
- "specified number of MiB. "
- "When we approach the limit the memory is released "
- "to the system more aggressively (more minor page faults). "
- "Zero means to allocate as long as system allows.");
-
-namespace tcmalloc {
-
-PageHeap::PageHeap()
- : pagemap_(MetaDataAlloc),
- pagemap_cache_(0),
- scavenge_counter_(0),
- // Start scavenging at kMaxPages list
- release_index_(kMaxPages),
- aggressive_decommit_(false) {
- COMPILE_ASSERT(kNumClasses <= (1 << PageMapCache::kValuebits), valuebits);
- DLL_Init(&large_.normal);
- DLL_Init(&large_.returned);
- for (int i = 0; i < kMaxPages; i++) {
- DLL_Init(&free_[i].normal);
- DLL_Init(&free_[i].returned);
- }
-}
-
-Span* PageHeap::SearchFreeAndLargeLists(Length n) {
- ASSERT(Check());
- ASSERT(n > 0);
-
- // Find first size >= n that has a non-empty list
- for (Length s = n; s < kMaxPages; s++) {
- Span* ll = &free_[s].normal;
- // If we're lucky, ll is non-empty, meaning it has a suitable span.
- if (!DLL_IsEmpty(ll)) {
- ASSERT(ll->next->location == Span::ON_NORMAL_FREELIST);
- return Carve(ll->next, n);
- }
- // Alternatively, maybe there's a usable returned span.
- ll = &free_[s].returned;
- if (!DLL_IsEmpty(ll)) {
- // We did not call EnsureLimit before, to avoid releasing the span
- // that will be taken immediately back.
- // Calling EnsureLimit here is not very expensive, as it fails only if
- // there is no more normal spans (and it fails efficiently)
- // or SystemRelease does not work (there is probably no returned spans).
- if (EnsureLimit(n)) {
- // ll may have became empty due to coalescing
- if (!DLL_IsEmpty(ll)) {
- ASSERT(ll->next->location == Span::ON_RETURNED_FREELIST);
- return Carve(ll->next, n);
- }
- }
- }
- }
- // No luck in free lists, our last chance is in a larger class.
- return AllocLarge(n); // May be NULL
-}
-
-static const size_t kForcedCoalesceInterval = 128*1024*1024;
-
-Span* PageHeap::New(Length n) {
- ASSERT(Check());
- ASSERT(n > 0);
-
- Span* result = SearchFreeAndLargeLists(n);
- if (result != NULL)
- return result;
-
- if (stats_.free_bytes != 0 && stats_.unmapped_bytes != 0
- && stats_.free_bytes + stats_.unmapped_bytes >= stats_.system_bytes / 4
- && (stats_.system_bytes / kForcedCoalesceInterval
- != (stats_.system_bytes + (n << kPageShift)) / kForcedCoalesceInterval)) {
- // We're about to grow heap, but there are lots of free pages.
- // tcmalloc's design decision to keep unmapped and free spans
- // separately and never coalesce them means that sometimes there
- // can be free pages span of sufficient size, but it consists of
- // "segments" of different type so page heap search cannot find
- // it. In order to prevent growing heap and wasting memory in such
- // case we're going to unmap all free pages. So that all free
- // spans are maximally coalesced.
- //
- // We're also limiting 'rate' of going into this path to be at
- // most once per 128 megs of heap growth. Otherwise programs that
- // grow heap frequently (and that means by small amount) could be
- // penalized with higher count of minor page faults.
- //
- // See also large_heap_fragmentation_unittest.cc and
- // https://code.google.com/p/gperftools/issues/detail?id=368
- ReleaseAtLeastNPages(static_cast<Length>(0x7fffffff));
-
- // then try again. If we are forced to grow heap because of large
- // spans fragmentation and not because of problem described above,
- // then at the very least we've just unmapped free but
- // insufficiently big large spans back to OS. So in case of really
- // unlucky memory fragmentation we'll be consuming virtual address
- // space, but not real memory
- result = SearchFreeAndLargeLists(n);
- if (result != NULL) return result;
- }
-
- // Grow the heap and try again.
- if (!GrowHeap(n)) {
- ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes);
- ASSERT(Check());
- // underlying SysAllocator likely set ENOMEM but we can get here
- // due to EnsureLimit so we set it here too.
- //
- // Setting errno to ENOMEM here allows us to avoid dealing with it
- // in fast-path.
- errno = ENOMEM;
- return NULL;
- }
- return SearchFreeAndLargeLists(n);
-}
-
-Span* PageHeap::AllocLarge(Length n) {
- // find the best span (closest to n in size).
- // The following loops implements address-ordered best-fit.
- Span *best = NULL;
-
- // Search through normal list
- for (Span* span = large_.normal.next;
- span != &large_.normal;
- span = span->next) {
- if (span->length >= n) {
- if ((best == NULL)
- || (span->length < best->length)
- || ((span->length == best->length) && (span->start < best->start))) {
- best = span;
- ASSERT(best->location == Span::ON_NORMAL_FREELIST);
- }
- }
- }
-
- Span *bestNormal = best;
-
- // Search through released list in case it has a better fit
- for (Span* span = large_.returned.next;
- span != &large_.returned;
- span = span->next) {
- if (span->length >= n) {
- if ((best == NULL)
- || (span->length < best->length)
- || ((span->length == best->length) && (span->start < best->start))) {
- best = span;
- ASSERT(best->location == Span::ON_RETURNED_FREELIST);
- }
- }
- }
-
- if (best == bestNormal) {
- return best == NULL ? NULL : Carve(best, n);
- }
-
- // best comes from returned list.
-
- if (EnsureLimit(n, false)) {
- return Carve(best, n);
- }
-
- if (EnsureLimit(n, true)) {
- // best could have been destroyed by coalescing.
- // bestNormal is not a best-fit, and it could be destroyed as well.
- // We retry, the limit is already ensured:
- return AllocLarge(n);
- }
-
- // If bestNormal existed, EnsureLimit would succeeded:
- ASSERT(bestNormal == NULL);
- // We are not allowed to take best from returned list.
- return NULL;
-}
-
-Span* PageHeap::Split(Span* span, Length n) {
- ASSERT(0 < n);
- ASSERT(n < span->length);
- ASSERT(span->location == Span::IN_USE);
- ASSERT(span->sizeclass == 0);
- Event(span, 'T', n);
-
- const int extra = span->length - n;
- Span* leftover = NewSpan(span->start + n, extra);
- ASSERT(leftover->location == Span::IN_USE);
- Event(leftover, 'U', extra);
- RecordSpan(leftover);
- pagemap_.set(span->start + n - 1, span); // Update map from pageid to span
- span->length = n;
-
- return leftover;
-}
-
-void PageHeap::CommitSpan(Span* span) {
- ++stats_.commit_count;
-
- TCMalloc_SystemCommit(reinterpret_cast<void*>(span->start << kPageShift),
- static_cast<size_t>(span->length << kPageShift));
- stats_.committed_bytes += span->length << kPageShift;
- stats_.total_commit_bytes += (span->length << kPageShift);
-}
-
-bool PageHeap::DecommitSpan(Span* span) {
- ++stats_.decommit_count;
-
- bool rv = TCMalloc_SystemRelease(reinterpret_cast<void*>(span->start << kPageShift),
- static_cast<size_t>(span->length << kPageShift));
- if (rv) {
- stats_.committed_bytes -= span->length << kPageShift;
- stats_.total_decommit_bytes += (span->length << kPageShift);
- }
-
- return rv;
-}
-
-Span* PageHeap::Carve(Span* span, Length n) {
- ASSERT(n > 0);
- ASSERT(span->location != Span::IN_USE);
- const int old_location = span->location;
- RemoveFromFreeList(span);
- span->location = Span::IN_USE;
- Event(span, 'A', n);
-
- const int extra = span->length - n;
- ASSERT(extra >= 0);
- if (extra > 0) {
- Span* leftover = NewSpan(span->start + n, extra);
- leftover->location = old_location;
- Event(leftover, 'S', extra);
- RecordSpan(leftover);
-
- // The previous span of |leftover| was just splitted -- no need to
- // coalesce them. The next span of |leftover| was not previously coalesced
- // with |span|, i.e. is NULL or has got location other than |old_location|.
-#ifndef NDEBUG
- const PageID p = leftover->start;
- const Length len = leftover->length;
- Span* next = GetDescriptor(p+len);
- ASSERT (next == NULL ||
- next->location == Span::IN_USE ||
- next->location != leftover->location);
-#endif
-
- PrependToFreeList(leftover); // Skip coalescing - no candidates possible
- span->length = n;
- pagemap_.set(span->start + n - 1, span);
- }
- ASSERT(Check());
- if (old_location == Span::ON_RETURNED_FREELIST) {
- // We need to recommit this address space.
- CommitSpan(span);
- }
- ASSERT(span->location == Span::IN_USE);
- ASSERT(span->length == n);
- ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes);
- return span;
-}
-
-void PageHeap::Delete(Span* span) {
- ASSERT(Check());
- ASSERT(span->location == Span::IN_USE);
- ASSERT(span->length > 0);
- ASSERT(GetDescriptor(span->start) == span);
- ASSERT(GetDescriptor(span->start + span->length - 1) == span);
- const Length n = span->length;
- span->sizeclass = 0;
- span->sample = 0;
- span->location = Span::ON_NORMAL_FREELIST;
- Event(span, 'D', span->length);
- MergeIntoFreeList(span); // Coalesces if possible
- IncrementalScavenge(n);
- ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes);
- ASSERT(Check());
-}
-
-bool PageHeap::MayMergeSpans(Span *span, Span *other) {
- if (aggressive_decommit_) {
- return other->location != Span::IN_USE;
- }
- return span->location == other->location;
-}
-
-void PageHeap::MergeIntoFreeList(Span* span) {
- ASSERT(span->location != Span::IN_USE);
-
- // Coalesce -- we guarantee that "p" != 0, so no bounds checking
- // necessary. We do not bother resetting the stale pagemap
- // entries for the pieces we are merging together because we only
- // care about the pagemap entries for the boundaries.
- //
- // Note: depending on aggressive_decommit_ mode we allow only
- // similar spans to be coalesced.
- //
- // The following applies if aggressive_decommit_ is enabled:
- //
- // Note that the adjacent spans we merge into "span" may come out of a
- // "normal" (committed) list, and cleanly merge with our IN_USE span, which
- // is implicitly committed. If the adjacents spans are on the "returned"
- // (decommitted) list, then we must get both spans into the same state before
- // or after we coalesce them. The current code always decomits. This is
- // achieved by blindly decommitting the entire coalesced region, which may
- // include any combination of committed and decommitted spans, at the end of
- // the method.
-
- // TODO(jar): "Always decommit" causes some extra calls to commit when we are
- // called in GrowHeap() during an allocation :-/. We need to eval the cost of
- // that oscillation, and possibly do something to reduce it.
-
- // TODO(jar): We need a better strategy for deciding to commit, or decommit,
- // based on memory usage and free heap sizes.
-
- uint64_t temp_committed = 0;
-
- const PageID p = span->start;
- const Length n = span->length;
- Span* prev = GetDescriptor(p-1);
- if (prev != NULL && MayMergeSpans(span, prev)) {
- // Merge preceding span into this span
- ASSERT(prev->start + prev->length == p);
- const Length len = prev->length;
- if (aggressive_decommit_ && prev->location == Span::ON_RETURNED_FREELIST) {
- // We're about to put the merge span into the returned freelist and call
- // DecommitSpan() on it, which will mark the entire span including this
- // one as released and decrease stats_.committed_bytes by the size of the
- // merged span. To make the math work out we temporarily increase the
- // stats_.committed_bytes amount.
- temp_committed = prev->length << kPageShift;
- }
- RemoveFromFreeList(prev);
- DeleteSpan(prev);
- span->start -= len;
- span->length += len;
- pagemap_.set(span->start, span);
- Event(span, 'L', len);
- }
- Span* next = GetDescriptor(p+n);
- if (next != NULL && MayMergeSpans(span, next)) {
- // Merge next span into this span
- ASSERT(next->start == p+n);
- const Length len = next->length;
- if (aggressive_decommit_ && next->location == Span::ON_RETURNED_FREELIST) {
- // See the comment below 'if (prev->location ...' for explanation.
- temp_committed += next->length << kPageShift;
- }
- RemoveFromFreeList(next);
- DeleteSpan(next);
- span->length += len;
- pagemap_.set(span->start + span->length - 1, span);
- Event(span, 'R', len);
- }
-
- if (aggressive_decommit_) {
- if (DecommitSpan(span)) {
- span->location = Span::ON_RETURNED_FREELIST;
- stats_.committed_bytes += temp_committed;
- } else {
- ASSERT(temp_committed == 0);
- }
- }
- PrependToFreeList(span);
-}
-
-void PageHeap::PrependToFreeList(Span* span) {
- ASSERT(span->location != Span::IN_USE);
- SpanList* list = (span->length < kMaxPages) ? &free_[span->length] : &large_;
- if (span->location == Span::ON_NORMAL_FREELIST) {
- stats_.free_bytes += (span->length << kPageShift);
- DLL_Prepend(&list->normal, span);
- } else {
- stats_.unmapped_bytes += (span->length << kPageShift);
- DLL_Prepend(&list->returned, span);
- }
-}
-
-void PageHeap::RemoveFromFreeList(Span* span) {
- ASSERT(span->location != Span::IN_USE);
- if (span->location == Span::ON_NORMAL_FREELIST) {
- stats_.free_bytes -= (span->length << kPageShift);
- } else {
- stats_.unmapped_bytes -= (span->length << kPageShift);
- }
- DLL_Remove(span);
-}
-
-void PageHeap::IncrementalScavenge(Length n) {
- // Fast path; not yet time to release memory
- scavenge_counter_ -= n;
- if (scavenge_counter_ >= 0) return; // Not yet time to scavenge
-
- const double rate = FLAGS_tcmalloc_release_rate;
- if (rate <= 1e-6) {
- // Tiny release rate means that releasing is disabled.
- scavenge_counter_ = kDefaultReleaseDelay;
- return;
- }
-
- ++stats_.scavenge_count;
-
- Length released_pages = ReleaseAtLeastNPages(1);
-
- if (released_pages == 0) {
- // Nothing to scavenge, delay for a while.
- scavenge_counter_ = kDefaultReleaseDelay;
- } else {
- // Compute how long to wait until we return memory.
- // FLAGS_tcmalloc_release_rate==1 means wait for 1000 pages
- // after releasing one page.
- const double mult = 1000.0 / rate;
- double wait = mult * static_cast<double>(released_pages);
- if (wait > kMaxReleaseDelay) {
- // Avoid overflow and bound to reasonable range.
- wait = kMaxReleaseDelay;
- }
- scavenge_counter_ = static_cast<int64_t>(wait);
- }
-}
-
-Length PageHeap::ReleaseLastNormalSpan(SpanList* slist) {
- Span* s = slist->normal.prev;
- ASSERT(s->location == Span::ON_NORMAL_FREELIST);
-
- if (DecommitSpan(s)) {
- RemoveFromFreeList(s);
- const Length n = s->length;
- s->location = Span::ON_RETURNED_FREELIST;
- MergeIntoFreeList(s); // Coalesces if possible.
- return n;
- }
-
- return 0;
-}
-
-Length PageHeap::ReleaseAtLeastNPages(Length num_pages) {
- Length released_pages = 0;
-
- // Round robin through the lists of free spans, releasing the last
- // span in each list. Stop after releasing at least num_pages
- // or when there is nothing more to release.
- while (released_pages < num_pages && stats_.free_bytes > 0) {
- for (int i = 0; i < kMaxPages+1 && released_pages < num_pages;
- i++, release_index_++) {
- if (release_index_ > kMaxPages) release_index_ = 0;
- SpanList* slist = (release_index_ == kMaxPages) ?
- &large_ : &free_[release_index_];
- if (!DLL_IsEmpty(&slist->normal)) {
- Length released_len = ReleaseLastNormalSpan(slist);
- // Some systems do not support release
- if (released_len == 0) return released_pages;
- released_pages += released_len;
- }
- }
- }
- return released_pages;
-}
-
-bool PageHeap::EnsureLimit(Length n, bool withRelease)
-{
- Length limit = (FLAGS_tcmalloc_heap_limit_mb*1024*1024) >> kPageShift;
- if (limit == 0) return true; //there is no limit
-
- // We do not use stats_.system_bytes because it does not take
- // MetaDataAllocs into account.
- Length takenPages = TCMalloc_SystemTaken >> kPageShift;
- //XXX takenPages may be slightly bigger than limit for two reasons:
- //* MetaDataAllocs ignore the limit (it is not easy to handle
- // out of memory there)
- //* sys_alloc may round allocation up to huge page size,
- // although smaller limit was ensured
-
- ASSERT(takenPages >= stats_.unmapped_bytes >> kPageShift);
- takenPages -= stats_.unmapped_bytes >> kPageShift;
-
- if (takenPages + n > limit && withRelease) {
- takenPages -= ReleaseAtLeastNPages(takenPages + n - limit);
- }
-
- return takenPages + n <= limit;
-}
-
-void PageHeap::RegisterSizeClass(Span* span, size_t sc) {
- // Associate span object with all interior pages as well
- ASSERT(span->location == Span::IN_USE);
- ASSERT(GetDescriptor(span->start) == span);
- ASSERT(GetDescriptor(span->start+span->length-1) == span);
- Event(span, 'C', sc);
- span->sizeclass = sc;
- for (Length i = 1; i < span->length-1; i++) {
- pagemap_.set(span->start+i, span);
- }
-}
-
-void PageHeap::GetSmallSpanStats(SmallSpanStats* result) {
- for (int s = 0; s < kMaxPages; s++) {
- result->normal_length[s] = DLL_Length(&free_[s].normal);
- result->returned_length[s] = DLL_Length(&free_[s].returned);
- }
-}
-
-void PageHeap::GetLargeSpanStats(LargeSpanStats* result) {
- result->spans = 0;
- result->normal_pages = 0;
- result->returned_pages = 0;
- for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) {
- result->normal_pages += s->length;;
- result->spans++;
- }
- for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) {
- result->returned_pages += s->length;
- result->spans++;
- }
-}
-
-bool PageHeap::GetNextRange(PageID start, base::MallocRange* r) {
- Span* span = reinterpret_cast<Span*>(pagemap_.Next(start));
- if (span == NULL) {
- return false;
- }
- r->address = span->start << kPageShift;
- r->length = span->length << kPageShift;
- r->fraction = 0;
- switch (span->location) {
- case Span::IN_USE:
- r->type = base::MallocRange::INUSE;
- r->fraction = 1;
- if (span->sizeclass > 0) {
- // Only some of the objects in this span may be in use.
- const size_t osize = Static::sizemap()->class_to_size(span->sizeclass);
- r->fraction = (1.0 * osize * span->refcount) / r->length;
- }
- break;
- case Span::ON_NORMAL_FREELIST:
- r->type = base::MallocRange::FREE;
- break;
- case Span::ON_RETURNED_FREELIST:
- r->type = base::MallocRange::UNMAPPED;
- break;
- default:
- r->type = base::MallocRange::UNKNOWN;
- break;
- }
- return true;
-}
-
-static void RecordGrowth(size_t growth) {
- StackTrace* t = Static::stacktrace_allocator()->New();
- t->depth = GetStackTrace(t->stack, kMaxStackDepth-1, 3);
- t->size = growth;
- t->stack[kMaxStackDepth-1] = reinterpret_cast<void*>(Static::growth_stacks());
- Static::set_growth_stacks(t);
-}
-
-bool PageHeap::GrowHeap(Length n) {
- ASSERT(kMaxPages >= kMinSystemAlloc);
- if (n > kMaxValidPages) return false;
- Length ask = (n>kMinSystemAlloc) ? n : static_cast<Length>(kMinSystemAlloc);
- size_t actual_size;
- void* ptr = NULL;
- if (EnsureLimit(ask)) {
- ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
- }
- if (ptr == NULL) {
- if (n < ask) {
- // Try growing just "n" pages
- ask = n;
- if (EnsureLimit(ask)) {
- ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
- }
- }
- if (ptr == NULL) return false;
- }
- ask = actual_size >> kPageShift;
- RecordGrowth(ask << kPageShift);
-
- ++stats_.reserve_count;
- ++stats_.commit_count;
-
- uint64_t old_system_bytes = stats_.system_bytes;
- stats_.system_bytes += (ask << kPageShift);
- stats_.committed_bytes += (ask << kPageShift);
-
- stats_.total_commit_bytes += (ask << kPageShift);
- stats_.total_reserve_bytes += (ask << kPageShift);
-
- const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
- ASSERT(p > 0);
-
- // If we have already a lot of pages allocated, just pre allocate a bunch of
- // memory for the page map. This prevents fragmentation by pagemap metadata
- // when a program keeps allocating and freeing large blocks.
-
- if (old_system_bytes < kPageMapBigAllocationThreshold
- && stats_.system_bytes >= kPageMapBigAllocationThreshold) {
- pagemap_.PreallocateMoreMemory();
- }
-
- // Make sure pagemap_ has entries for all of the new pages.
- // Plus ensure one before and one after so coalescing code
- // does not need bounds-checking.
- if (pagemap_.Ensure(p-1, ask+2)) {
- // Pretend the new area is allocated and then Delete() it to cause
- // any necessary coalescing to occur.
- Span* span = NewSpan(p, ask);
- RecordSpan(span);
- Delete(span);
- ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes);
- ASSERT(Check());
- return true;
- } else {
- // We could not allocate memory within "pagemap_"
- // TODO: Once we can return memory to the system, return the new span
- return false;
- }
-}
-
-bool PageHeap::Check() {
- ASSERT(free_[0].normal.next == &free_[0].normal);
- ASSERT(free_[0].returned.next == &free_[0].returned);
- return true;
-}
-
-bool PageHeap::CheckExpensive() {
- bool result = Check();
- CheckList(&large_.normal, kMaxPages, 1000000000, Span::ON_NORMAL_FREELIST);
- CheckList(&large_.returned, kMaxPages, 1000000000, Span::ON_RETURNED_FREELIST);
- for (Length s = 1; s < kMaxPages; s++) {
- CheckList(&free_[s].normal, s, s, Span::ON_NORMAL_FREELIST);
- CheckList(&free_[s].returned, s, s, Span::ON_RETURNED_FREELIST);
- }
- return result;
-}
-
-bool PageHeap::CheckList(Span* list, Length min_pages, Length max_pages,
- int freelist) {
- for (Span* s = list->next; s != list; s = s->next) {
- CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED
- CHECK_CONDITION(s->length >= min_pages);
- CHECK_CONDITION(s->length <= max_pages);
- CHECK_CONDITION(GetDescriptor(s->start) == s);
- CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s);
- }
- return true;
-}
-
-} // namespace tcmalloc
diff --git a/src/third_party/gperftools-2.5/src/page_heap.h b/src/third_party/gperftools-2.5/src/page_heap.h
deleted file mode 100644
index 5c6607bbf16..00000000000
--- a/src/third_party/gperftools-2.5/src/page_heap.h
+++ /dev/null
@@ -1,328 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-
-#ifndef TCMALLOC_PAGE_HEAP_H_
-#define TCMALLOC_PAGE_HEAP_H_
-
-#include <config.h>
-#include <stddef.h> // for size_t
-#ifdef HAVE_STDINT_H
-#include <stdint.h> // for uint64_t, int64_t, uint16_t
-#endif
-#include <gperftools/malloc_extension.h>
-#include "base/basictypes.h"
-#include "common.h"
-#include "packed-cache-inl.h"
-#include "pagemap.h"
-#include "span.h"
-
-// We need to dllexport PageHeap just for the unittest. MSVC complains
-// that we don't dllexport the PageHeap members, but we don't need to
-// test those, so I just suppress this warning.
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4251)
-#endif
-
-// This #ifdef should almost never be set. Set NO_TCMALLOC_SAMPLES if
-// you're porting to a system where you really can't get a stacktrace.
-// Because we control the definition of GetStackTrace, all clients of
-// GetStackTrace should #include us rather than stacktrace.h.
-#ifdef NO_TCMALLOC_SAMPLES
- // We use #define so code compiles even if you #include stacktrace.h somehow.
-# define GetStackTrace(stack, depth, skip) (0)
-#else
-# include <gperftools/stacktrace.h>
-#endif
-
-namespace base {
-struct MallocRange;
-}
-
-namespace tcmalloc {
-
-// -------------------------------------------------------------------------
-// Map from page-id to per-page data
-// -------------------------------------------------------------------------
-
-// We use PageMap2<> for 32-bit and PageMap3<> for 64-bit machines.
-// We also use a simple one-level cache for hot PageID-to-sizeclass mappings,
-// because sometimes the sizeclass is all the information we need.
-
-// Selector class -- general selector uses 3-level map
-template <int BITS> class MapSelector {
- public:
- typedef TCMalloc_PageMap3<BITS-kPageShift> Type;
- typedef PackedCache<BITS-kPageShift, uint64_t> CacheType;
-};
-
-// A two-level map for 32-bit machines
-template <> class MapSelector<32> {
- public:
- typedef TCMalloc_PageMap2<32-kPageShift> Type;
- typedef PackedCache<32-kPageShift, uint16_t> CacheType;
-};
-
-// -------------------------------------------------------------------------
-// Page-level allocator
-// * Eager coalescing
-//
-// Heap for page-level allocation. We allow allocating and freeing a
-// contiguous runs of pages (called a "span").
-// -------------------------------------------------------------------------
-
-class PERFTOOLS_DLL_DECL PageHeap {
- public:
- PageHeap();
-
- // Allocate a run of "n" pages. Returns zero if out of memory.
- // Caller should not pass "n == 0" -- instead, n should have
- // been rounded up already.
- Span* New(Length n);
-
- // Delete the span "[p, p+n-1]".
- // REQUIRES: span was returned by earlier call to New() and
- // has not yet been deleted.
- void Delete(Span* span);
-
- // Mark an allocated span as being used for small objects of the
- // specified size-class.
- // REQUIRES: span was returned by an earlier call to New()
- // and has not yet been deleted.
- void RegisterSizeClass(Span* span, size_t sc);
-
- // Split an allocated span into two spans: one of length "n" pages
- // followed by another span of length "span->length - n" pages.
- // Modifies "*span" to point to the first span of length "n" pages.
- // Returns a pointer to the second span.
- //
- // REQUIRES: "0 < n < span->length"
- // REQUIRES: span->location == IN_USE
- // REQUIRES: span->sizeclass == 0
- Span* Split(Span* span, Length n);
-
- // Return the descriptor for the specified page. Returns NULL if
- // this PageID was not allocated previously.
- inline Span* GetDescriptor(PageID p) const {
- return reinterpret_cast<Span*>(pagemap_.get(p));
- }
-
- // If this page heap is managing a range with starting page # >= start,
- // store info about the range in *r and return true. Else return false.
- bool GetNextRange(PageID start, base::MallocRange* r);
-
- // Page heap statistics
- struct Stats {
- Stats() : system_bytes(0), free_bytes(0), unmapped_bytes(0), committed_bytes(0),
- scavenge_count(0), commit_count(0), decommit_count(0),
- total_commit_bytes(0), total_decommit_bytes(0),
- reserve_count(0), total_reserve_bytes(0) {}
- uint64_t system_bytes; // Total bytes allocated from system
- uint64_t free_bytes; // Total bytes on normal freelists
- uint64_t unmapped_bytes; // Total bytes on returned freelists
- uint64_t committed_bytes; // Bytes committed, always <= system_bytes_.
-
- uint64_t scavenge_count; // Number of times scavagened flush pages
-
- uint64_t commit_count; // Number of virtual memory commits
- uint64_t total_commit_bytes; // Bytes committed in lifetime of process
- uint64_t decommit_count; // Number of virtual memory decommits
- uint64_t total_decommit_bytes; // Bytes decommitted in lifetime of process
-
- uint64_t reserve_count; // Number of virtual memory reserves
- uint64_t total_reserve_bytes; // Bytes reserved in lifetime of process
- };
- inline Stats stats() const { return stats_; }
-
- struct SmallSpanStats {
- // For each free list of small spans, the length (in spans) of the
- // normal and returned free lists for that size.
- int64 normal_length[kMaxPages];
- int64 returned_length[kMaxPages];
- };
- void GetSmallSpanStats(SmallSpanStats* result);
-
- // Stats for free large spans (i.e., spans with more than kMaxPages pages).
- struct LargeSpanStats {
- int64 spans; // Number of such spans
- int64 normal_pages; // Combined page length of normal large spans
- int64 returned_pages; // Combined page length of unmapped spans
- };
- void GetLargeSpanStats(LargeSpanStats* result);
-
- bool Check();
- // Like Check() but does some more comprehensive checking.
- bool CheckExpensive();
- bool CheckList(Span* list, Length min_pages, Length max_pages,
- int freelist); // ON_NORMAL_FREELIST or ON_RETURNED_FREELIST
-
- // Try to release at least num_pages for reuse by the OS. Returns
- // the actual number of pages released, which may be less than
- // num_pages if there weren't enough pages to release. The result
- // may also be larger than num_pages since page_heap might decide to
- // release one large range instead of fragmenting it into two
- // smaller released and unreleased ranges.
- Length ReleaseAtLeastNPages(Length num_pages);
-
- // Return 0 if we have no information, or else the correct sizeclass for p.
- // Reads and writes to pagemap_cache_ do not require locking.
- // The entries are 64 bits on 64-bit hardware and 16 bits on
- // 32-bit hardware, and we don't mind raciness as long as each read of
- // an entry yields a valid entry, not a partially updated entry.
- size_t GetSizeClassIfCached(PageID p) const {
- return pagemap_cache_.GetOrDefault(p, 0);
- }
- void CacheSizeClass(PageID p, size_t cl) const { pagemap_cache_.Put(p, cl); }
-
- bool GetAggressiveDecommit(void) {return aggressive_decommit_;}
- void SetAggressiveDecommit(bool aggressive_decommit) {
- aggressive_decommit_ = aggressive_decommit;
- }
-
- private:
- // Allocates a big block of memory for the pagemap once we reach more than
- // 128MB
- static const size_t kPageMapBigAllocationThreshold = 128 << 20;
-
- // Minimum number of pages to fetch from system at a time. Must be
- // significantly bigger than kBlockSize to amortize system-call
- // overhead, and also to reduce external fragementation. Also, we
- // should keep this value big because various incarnations of Linux
- // have small limits on the number of mmap() regions per
- // address-space.
- // REQUIRED: kMinSystemAlloc <= kMaxPages;
- static const int kMinSystemAlloc = kMaxPages;
-
- // Never delay scavenging for more than the following number of
- // deallocated pages. With 4K pages, this comes to 4GB of
- // deallocation.
- static const int kMaxReleaseDelay = 1 << 20;
-
- // If there is nothing to release, wait for so many pages before
- // scavenging again. With 4K pages, this comes to 1GB of memory.
- static const int kDefaultReleaseDelay = 1 << 18;
-
- // Pick the appropriate map and cache types based on pointer size
- typedef MapSelector<kAddressBits>::Type PageMap;
- typedef MapSelector<kAddressBits>::CacheType PageMapCache;
- PageMap pagemap_;
- mutable PageMapCache pagemap_cache_;
-
- // We segregate spans of a given size into two circular linked
- // lists: one for normal spans, and one for spans whose memory
- // has been returned to the system.
- struct SpanList {
- Span normal;
- Span returned;
- };
-
- // List of free spans of length >= kMaxPages
- SpanList large_;
-
- // Array mapping from span length to a doubly linked list of free spans
- SpanList free_[kMaxPages];
-
- // Statistics on system, free, and unmapped bytes
- Stats stats_;
-
- Span* SearchFreeAndLargeLists(Length n);
-
- bool GrowHeap(Length n);
-
- // REQUIRES: span->length >= n
- // REQUIRES: span->location != IN_USE
- // Remove span from its free list, and move any leftover part of
- // span into appropriate free lists. Also update "span" to have
- // length exactly "n" and mark it as non-free so it can be returned
- // to the client. After all that, decrease free_pages_ by n and
- // return span.
- Span* Carve(Span* span, Length n);
-
- void RecordSpan(Span* span) {
- pagemap_.set(span->start, span);
- if (span->length > 1) {
- pagemap_.set(span->start + span->length - 1, span);
- }
- }
-
- // Allocate a large span of length == n. If successful, returns a
- // span of exactly the specified length. Else, returns NULL.
- Span* AllocLarge(Length n);
-
- // Coalesce span with neighboring spans if possible, prepend to
- // appropriate free list, and adjust stats.
- void MergeIntoFreeList(Span* span);
-
- // Commit the span.
- void CommitSpan(Span* span);
-
- // Decommit the span.
- bool DecommitSpan(Span* span);
-
- // Prepends span to appropriate free list, and adjusts stats.
- void PrependToFreeList(Span* span);
-
- // Removes span from its free list, and adjust stats.
- void RemoveFromFreeList(Span* span);
-
- // Incrementally release some memory to the system.
- // IncrementalScavenge(n) is called whenever n pages are freed.
- void IncrementalScavenge(Length n);
-
- // Release the last span on the normal portion of this list.
- // Return the length of that span or zero if release failed.
- Length ReleaseLastNormalSpan(SpanList* slist);
-
- // Checks if we are allowed to take more memory from the system.
- // If limit is reached and allowRelease is true, tries to release
- // some unused spans.
- bool EnsureLimit(Length n, bool allowRelease = true);
-
- bool MayMergeSpans(Span *span, Span *other);
-
- // Number of pages to deallocate before doing more scavenging
- int64_t scavenge_counter_;
-
- // Index of last free list where we released memory to the OS.
- int release_index_;
-
- bool aggressive_decommit_;
-};
-
-} // namespace tcmalloc
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-#endif // TCMALLOC_PAGE_HEAP_H_
diff --git a/src/third_party/gperftools-2.5/src/page_heap_allocator.h b/src/third_party/gperftools-2.5/src/page_heap_allocator.h
deleted file mode 100644
index 892d1c1abe3..00000000000
--- a/src/third_party/gperftools-2.5/src/page_heap_allocator.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-
-#ifndef TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
-#define TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
-
-#include <stddef.h> // for NULL, size_t
-
-#include "common.h" // for MetaDataAlloc
-#include "internal_logging.h" // for ASSERT
-
-namespace tcmalloc {
-
-// Simple allocator for objects of a specified type. External locking
-// is required before accessing one of these objects.
-template <class T>
-class PageHeapAllocator {
- public:
- // We use an explicit Init function because these variables are statically
- // allocated and their constructors might not have run by the time some
- // other static variable tries to allocate memory.
- void Init() {
- ASSERT(sizeof(T) <= kAllocIncrement);
- inuse_ = 0;
- free_area_ = NULL;
- free_avail_ = 0;
- free_list_ = NULL;
- // Reserve some space at the beginning to avoid fragmentation.
- Delete(New());
- }
-
- T* New() {
- // Consult free list
- void* result;
- if (free_list_ != NULL) {
- result = free_list_;
- free_list_ = *(reinterpret_cast<void**>(result));
- } else {
- if (free_avail_ < sizeof(T)) {
- // Need more room. We assume that MetaDataAlloc returns
- // suitably aligned memory.
- free_area_ = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
- if (free_area_ == NULL) {
- Log(kCrash, __FILE__, __LINE__,
- "FATAL ERROR: Out of memory trying to allocate internal "
- "tcmalloc data (bytes, object-size)",
- kAllocIncrement, sizeof(T));
- }
- free_avail_ = kAllocIncrement;
- }
- result = free_area_;
- free_area_ += sizeof(T);
- free_avail_ -= sizeof(T);
- }
- inuse_++;
- return reinterpret_cast<T*>(result);
- }
-
- void Delete(T* p) {
- *(reinterpret_cast<void**>(p)) = free_list_;
- free_list_ = p;
- inuse_--;
- }
-
- int inuse() const { return inuse_; }
-
- private:
- // How much to allocate from system at a time
- static const int kAllocIncrement = 128 << 10;
-
- // Free area from which to carve new objects
- char* free_area_;
- size_t free_avail_;
-
- // Free list of already carved objects
- void* free_list_;
-
- // Number of allocated but unfreed objects
- int inuse_;
-};
-
-} // namespace tcmalloc
-
-#endif // TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
diff --git a/src/third_party/gperftools-2.5/src/pagemap.h b/src/third_party/gperftools-2.5/src/pagemap.h
deleted file mode 100644
index dd9442313af..00000000000
--- a/src/third_party/gperftools-2.5/src/pagemap.h
+++ /dev/null
@@ -1,324 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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>
-//
-// A data structure used by the caching malloc. It maps from page# to
-// a pointer that contains info about that page. We use two
-// representations: one for 32-bit addresses, and another for 64 bit
-// addresses. Both representations provide the same interface. The
-// first representation is implemented as a flat array, the seconds as
-// a three-level radix tree that strips away approximately 1/3rd of
-// the bits every time.
-//
-// The BITS parameter should be the number of bits required to hold
-// a page number. E.g., with 32 bit pointers and 4K pages (i.e.,
-// page offset fits in lower 12 bits), BITS == 20.
-
-#ifndef TCMALLOC_PAGEMAP_H_
-#define TCMALLOC_PAGEMAP_H_
-
-#include "config.h"
-
-#include <stddef.h> // for NULL, size_t
-#include <string.h> // for memset
-#if defined HAVE_STDINT_H
-#include <stdint.h>
-#elif defined HAVE_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <sys/types.h>
-#endif
-#include "internal_logging.h" // for ASSERT
-
-// Single-level array
-template <int BITS>
-class TCMalloc_PageMap1 {
- private:
- static const int LENGTH = 1 << BITS;
-
- void** array_;
-
- public:
- typedef uintptr_t Number;
-
- explicit TCMalloc_PageMap1(void* (*allocator)(size_t)) {
- array_ = reinterpret_cast<void**>((*allocator)(sizeof(void*) << BITS));
- memset(array_, 0, sizeof(void*) << BITS);
- }
-
- // Ensure that the map contains initialized entries "x .. x+n-1".
- // Returns true if successful, false if we could not allocate memory.
- bool Ensure(Number x, size_t n) {
- // Nothing to do since flat array was allocated at start. All
- // that's left is to check for overflow (that is, we don't want to
- // ensure a number y where array_[y] would be an out-of-bounds
- // access).
- return n <= LENGTH - x; // an overflow-free way to do "x + n <= LENGTH"
- }
-
- void PreallocateMoreMemory() {}
-
- // Return the current value for KEY. Returns NULL if not yet set,
- // or if k is out of range.
- void* get(Number k) const {
- if ((k >> BITS) > 0) {
- return NULL;
- }
- return array_[k];
- }
-
- // REQUIRES "k" is in range "[0,2^BITS-1]".
- // REQUIRES "k" has been ensured before.
- //
- // Sets the value 'v' for key 'k'.
- void set(Number k, void* v) {
- array_[k] = v;
- }
-
- // Return the first non-NULL pointer found in this map for
- // a page number >= k. Returns NULL if no such number is found.
- void* Next(Number k) const {
- while (k < (1 << BITS)) {
- if (array_[k] != NULL) return array_[k];
- k++;
- }
- return NULL;
- }
-};
-
-// Two-level radix tree
-template <int BITS>
-class TCMalloc_PageMap2 {
- private:
- // Put 32 entries in the root and (2^BITS)/32 entries in each leaf.
- static const int ROOT_BITS = 5;
- static const int ROOT_LENGTH = 1 << ROOT_BITS;
-
- static const int LEAF_BITS = BITS - ROOT_BITS;
- static const int LEAF_LENGTH = 1 << LEAF_BITS;
-
- // Leaf node
- struct Leaf {
- void* values[LEAF_LENGTH];
- };
-
- Leaf* root_[ROOT_LENGTH]; // Pointers to 32 child nodes
- void* (*allocator_)(size_t); // Memory allocator
-
- public:
- typedef uintptr_t Number;
-
- explicit TCMalloc_PageMap2(void* (*allocator)(size_t)) {
- allocator_ = allocator;
- memset(root_, 0, sizeof(root_));
- }
-
- void* get(Number k) const {
- const Number i1 = k >> LEAF_BITS;
- const Number i2 = k & (LEAF_LENGTH-1);
- if ((k >> BITS) > 0 || root_[i1] == NULL) {
- return NULL;
- }
- return root_[i1]->values[i2];
- }
-
- void set(Number k, void* v) {
- const Number i1 = k >> LEAF_BITS;
- const Number i2 = k & (LEAF_LENGTH-1);
- ASSERT(i1 < ROOT_LENGTH);
- root_[i1]->values[i2] = v;
- }
-
- bool Ensure(Number start, size_t n) {
- for (Number key = start; key <= start + n - 1; ) {
- const Number i1 = key >> LEAF_BITS;
-
- // Check for overflow
- if (i1 >= ROOT_LENGTH)
- return false;
-
- // Make 2nd level node if necessary
- if (root_[i1] == NULL) {
- Leaf* leaf = reinterpret_cast<Leaf*>((*allocator_)(sizeof(Leaf)));
- if (leaf == NULL) return false;
- memset(leaf, 0, sizeof(*leaf));
- root_[i1] = leaf;
- }
-
- // Advance key past whatever is covered by this leaf node
- key = ((key >> LEAF_BITS) + 1) << LEAF_BITS;
- }
- return true;
- }
-
- void PreallocateMoreMemory() {
- // Allocate enough to keep track of all possible pages
- Ensure(0, 1 << BITS);
- }
-
- void* Next(Number k) const {
- while (k < (1 << BITS)) {
- const Number i1 = k >> LEAF_BITS;
- Leaf* leaf = root_[i1];
- if (leaf != NULL) {
- // Scan forward in leaf
- for (Number i2 = k & (LEAF_LENGTH - 1); i2 < LEAF_LENGTH; i2++) {
- if (leaf->values[i2] != NULL) {
- return leaf->values[i2];
- }
- }
- }
- // Skip to next top-level entry
- k = (i1 + 1) << LEAF_BITS;
- }
- return NULL;
- }
-};
-
-// Three-level radix tree
-template <int BITS>
-class TCMalloc_PageMap3 {
- private:
- // How many bits should we consume at each interior level
- static const int INTERIOR_BITS = (BITS + 2) / 3; // Round-up
- static const int INTERIOR_LENGTH = 1 << INTERIOR_BITS;
-
- // How many bits should we consume at leaf level
- static const int LEAF_BITS = BITS - 2*INTERIOR_BITS;
- static const int LEAF_LENGTH = 1 << LEAF_BITS;
-
- // Interior node
- struct Node {
- Node* ptrs[INTERIOR_LENGTH];
- };
-
- // Leaf node
- struct Leaf {
- void* values[LEAF_LENGTH];
- };
-
- Node* root_; // Root of radix tree
- void* (*allocator_)(size_t); // Memory allocator
-
- Node* NewNode() {
- Node* result = reinterpret_cast<Node*>((*allocator_)(sizeof(Node)));
- if (result != NULL) {
- memset(result, 0, sizeof(*result));
- }
- return result;
- }
-
- public:
- typedef uintptr_t Number;
-
- explicit TCMalloc_PageMap3(void* (*allocator)(size_t)) {
- allocator_ = allocator;
- root_ = NewNode();
- }
-
- void* get(Number k) const {
- const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS);
- const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1);
- const Number i3 = k & (LEAF_LENGTH-1);
- if ((k >> BITS) > 0 ||
- root_->ptrs[i1] == NULL || root_->ptrs[i1]->ptrs[i2] == NULL) {
- return NULL;
- }
- return reinterpret_cast<Leaf*>(root_->ptrs[i1]->ptrs[i2])->values[i3];
- }
-
- void set(Number k, void* v) {
- ASSERT(k >> BITS == 0);
- const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS);
- const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1);
- const Number i3 = k & (LEAF_LENGTH-1);
- reinterpret_cast<Leaf*>(root_->ptrs[i1]->ptrs[i2])->values[i3] = v;
- }
-
- bool Ensure(Number start, size_t n) {
- for (Number key = start; key <= start + n - 1; ) {
- const Number i1 = key >> (LEAF_BITS + INTERIOR_BITS);
- const Number i2 = (key >> LEAF_BITS) & (INTERIOR_LENGTH-1);
-
- // Check for overflow
- if (i1 >= INTERIOR_LENGTH || i2 >= INTERIOR_LENGTH)
- return false;
-
- // Make 2nd level node if necessary
- if (root_->ptrs[i1] == NULL) {
- Node* n = NewNode();
- if (n == NULL) return false;
- root_->ptrs[i1] = n;
- }
-
- // Make leaf node if necessary
- if (root_->ptrs[i1]->ptrs[i2] == NULL) {
- Leaf* leaf = reinterpret_cast<Leaf*>((*allocator_)(sizeof(Leaf)));
- if (leaf == NULL) return false;
- memset(leaf, 0, sizeof(*leaf));
- root_->ptrs[i1]->ptrs[i2] = reinterpret_cast<Node*>(leaf);
- }
-
- // Advance key past whatever is covered by this leaf node
- key = ((key >> LEAF_BITS) + 1) << LEAF_BITS;
- }
- return true;
- }
-
- void PreallocateMoreMemory() {
- }
-
- void* Next(Number k) const {
- while (k < (Number(1) << BITS)) {
- const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS);
- const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1);
- if (root_->ptrs[i1] == NULL) {
- // Advance to next top-level entry
- k = (i1 + 1) << (LEAF_BITS + INTERIOR_BITS);
- } else {
- Leaf* leaf = reinterpret_cast<Leaf*>(root_->ptrs[i1]->ptrs[i2]);
- if (leaf != NULL) {
- for (Number i3 = (k & (LEAF_LENGTH-1)); i3 < LEAF_LENGTH; i3++) {
- if (leaf->values[i3] != NULL) {
- return leaf->values[i3];
- }
- }
- }
- // Advance to next interior entry
- k = ((k >> LEAF_BITS) + 1) << LEAF_BITS;
- }
- }
- return NULL;
- }
-};
-
-#endif // TCMALLOC_PAGEMAP_H_
diff --git a/src/third_party/gperftools-2.5/src/pprof b/src/third_party/gperftools-2.5/src/pprof
deleted file mode 100755
index bee51bf9985..00000000000
--- a/src/third_party/gperftools-2.5/src/pprof
+++ /dev/null
@@ -1,5590 +0,0 @@
-#! /usr/bin/env perl
-
-# Copyright (c) 1998-2007, 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.
-
-# ---
-# Program for printing the profile generated by common/profiler.cc,
-# or by the heap profiler (common/debugallocation.cc)
-#
-# The profile contains a sequence of entries of the form:
-# <count> <stack trace>
-# This program parses the profile, and generates user-readable
-# output.
-#
-# Examples:
-#
-# % tools/pprof "program" "profile"
-# Enters "interactive" mode
-#
-# % tools/pprof --text "program" "profile"
-# Generates one line per procedure
-#
-# % tools/pprof --gv "program" "profile"
-# Generates annotated call-graph and displays via "gv"
-#
-# % tools/pprof --gv --focus=Mutex "program" "profile"
-# Restrict to code paths that involve an entry that matches "Mutex"
-#
-# % tools/pprof --gv --focus=Mutex --ignore=string "program" "profile"
-# Restrict to code paths that involve an entry that matches "Mutex"
-# and does not match "string"
-#
-# % tools/pprof --list=IBF_CheckDocid "program" "profile"
-# Generates disassembly listing of all routines with at least one
-# sample that match the --list=<regexp> pattern. The listing is
-# annotated with the flat and cumulative sample counts at each line.
-#
-# % tools/pprof --disasm=IBF_CheckDocid "program" "profile"
-# Generates disassembly listing of all routines with at least one
-# sample that match the --disasm=<regexp> pattern. The listing is
-# annotated with the flat and cumulative sample counts at each PC value.
-#
-# TODO: Use color to indicate files?
-
-use strict;
-use warnings;
-use Getopt::Long;
-use Cwd;
-use POSIX;
-
-my $PPROF_VERSION = "2.0";
-
-# These are the object tools we use which can come from a
-# user-specified location using --tools, from the PPROF_TOOLS
-# environment variable, or from the environment.
-my %obj_tool_map = (
- "objdump" => "objdump",
- "nm" => "nm",
- "addr2line" => "addr2line",
- "c++filt" => "c++filt",
- ## ConfigureObjTools may add architecture-specific entries:
- #"nm_pdb" => "nm-pdb", # for reading windows (PDB-format) executables
- #"addr2line_pdb" => "addr2line-pdb", # ditto
- #"otool" => "otool", # equivalent of objdump on OS X
-);
-# NOTE: these are lists, so you can put in commandline flags if you want.
-my @DOT = ("dot"); # leave non-absolute, since it may be in /usr/local
-my @GV = ("gv");
-my @EVINCE = ("evince"); # could also be xpdf or perhaps acroread
-my @KCACHEGRIND = ("kcachegrind");
-my @PS2PDF = ("ps2pdf");
-# These are used for dynamic profiles
-my @URL_FETCHER = ("curl", "-s");
-
-# These are the web pages that servers need to support for dynamic profiles
-my $HEAP_PAGE = "/pprof/heap";
-my $PROFILE_PAGE = "/pprof/profile"; # must support cgi-param "?seconds=#"
-my $PMUPROFILE_PAGE = "/pprof/pmuprofile(?:\\?.*)?"; # must support cgi-param
- # ?seconds=#&event=x&period=n
-my $GROWTH_PAGE = "/pprof/growth";
-my $CONTENTION_PAGE = "/pprof/contention";
-my $WALL_PAGE = "/pprof/wall(?:\\?.*)?"; # accepts options like namefilter
-my $FILTEREDPROFILE_PAGE = "/pprof/filteredprofile(?:\\?.*)?";
-my $CENSUSPROFILE_PAGE = "/pprof/censusprofile(?:\\?.*)?"; # must support cgi-param
- # "?seconds=#",
- # "?tags_regexp=#" and
- # "?type=#".
-my $SYMBOL_PAGE = "/pprof/symbol"; # must support symbol lookup via POST
-my $PROGRAM_NAME_PAGE = "/pprof/cmdline";
-
-# These are the web pages that can be named on the command line.
-# All the alternatives must begin with /.
-my $PROFILES = "($HEAP_PAGE|$PROFILE_PAGE|$PMUPROFILE_PAGE|" .
- "$GROWTH_PAGE|$CONTENTION_PAGE|$WALL_PAGE|" .
- "$FILTEREDPROFILE_PAGE|$CENSUSPROFILE_PAGE)";
-
-# default binary name
-my $UNKNOWN_BINARY = "(unknown)";
-
-# There is a pervasive dependency on the length (in hex characters,
-# i.e., nibbles) of an address, distinguishing between 32-bit and
-# 64-bit profiles. To err on the safe size, default to 64-bit here:
-my $address_length = 16;
-
-my $dev_null = "/dev/null";
-if (! -e $dev_null && $^O =~ /MSWin/) { # $^O is the OS perl was built for
- $dev_null = "nul";
-}
-
-# A list of paths to search for shared object files
-my @prefix_list = ();
-
-# Special routine name that should not have any symbols.
-# Used as separator to parse "addr2line -i" output.
-my $sep_symbol = '_fini';
-my $sep_address = undef;
-
-my @stackTraces;
-
-##### Argument parsing #####
-
-sub usage_string {
- return <<EOF;
-Usage:
-$0 [options] <program> <profiles>
- <profiles> is a space separated list of profile names.
-$0 [options] <symbolized-profiles>
- <symbolized-profiles> is a list of profile files where each file contains
- the necessary symbol mappings as well as profile data (likely generated
- with --raw).
-$0 [options] <profile>
- <profile> is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE
-
- Each name can be:
- /path/to/profile - a path to a profile file
- host:port[/<service>] - a location of a service to get profile from
-
- The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,
- $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,
- $CENSUSPROFILE_PAGE, or /pprof/filteredprofile.
- For instance:
- $0 http://myserver.com:80$HEAP_PAGE
- If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling).
-$0 --symbols <program>
- Maps addresses to symbol names. In this mode, stdin should be a
- list of library mappings, in the same format as is found in the heap-
- and cpu-profile files (this loosely matches that of /proc/self/maps
- on linux), followed by a list of hex addresses to map, one per line.
-
- For more help with querying remote servers, including how to add the
- necessary server-side support code, see this filename (or one like it):
-
- /usr/doc/gperftools-$PPROF_VERSION/pprof_remote_servers.html
-
-Options:
- --cum Sort by cumulative data
- --base=<base> Subtract <base> from <profile> before display
- --interactive Run in interactive mode (interactive "help" gives help) [default]
- --seconds=<n> Length of time for dynamic profiles [default=30 secs]
- --add_lib=<file> Read additional symbols and line info from the given library
- --lib_prefix=<dir> Comma separated list of library path prefixes
- --no_strip_temp Do not strip template arguments from function names
-
-Reporting Granularity:
- --addresses Report at address level
- --lines Report at source line level
- --functions Report at function level [default]
- --files Report at source file level
-
-Output type:
- --text Generate text report
- --stacks Generate stack traces similar to the heap profiler (requires --text)
- --callgrind Generate callgrind format to stdout
- --gv Generate Postscript and display
- --evince Generate PDF and display
- --web Generate SVG and display
- --list=<regexp> Generate source listing of matching routines
- --disasm=<regexp> Generate disassembly of matching routines
- --symbols Print demangled symbol names found at given addresses
- --dot Generate DOT file to stdout
- --ps Generate Postcript to stdout
- --pdf Generate PDF to stdout
- --svg Generate SVG to stdout
- --gif Generate GIF to stdout
- --raw Generate symbolized pprof data (useful with remote fetch)
- --collapsed Generate collapsed stacks for building flame graphs
- (see http://www.brendangregg.com/flamegraphs.html)
-
-Heap-Profile Options:
- --inuse_space Display in-use (mega)bytes [default]
- --inuse_objects Display in-use objects
- --alloc_space Display allocated (mega)bytes
- --alloc_objects Display allocated objects
- --show_bytes Display space in bytes
- --drop_negative Ignore negative differences
-
-Contention-profile options:
- --total_delay Display total delay at each region [default]
- --contentions Display number of delays at each region
- --mean_delay Display mean delay at each region
-
-Call-graph Options:
- --nodecount=<n> Show at most so many nodes [default=80]
- --nodefraction=<f> Hide nodes below <f>*total [default=.005]
- --edgefraction=<f> Hide edges below <f>*total [default=.001]
- --maxdegree=<n> Max incoming/outgoing edges per node [default=8]
- --focus=<regexp> Focus on nodes matching <regexp>
- --ignore=<regexp> Ignore nodes matching <regexp>
- --scale=<n> Set GV scaling [default=0]
- --heapcheck Make nodes with non-0 object counts
- (i.e. direct leak generators) more visible
-
-Miscellaneous:
- --no-auto-signal-frm Automatically drop 2nd frame that is always same (cpu-only)
- (assuming that it is artifact of bad stack captures
- which include signal handler frames)
- --show_addresses Always show addresses when applicable
- --tools=<prefix or binary:fullpath>[,...] \$PATH for object tool pathnames
- --test Run unit tests
- --help This message
- --version Version information
-
-Environment Variables:
- PPROF_TMPDIR Profiles directory. Defaults to \$HOME/pprof
- PPROF_TOOLS Prefix for object tools pathnames
-
-Examples:
-
-$0 /bin/ls ls.prof
- Enters "interactive" mode
-$0 --text /bin/ls ls.prof
- Outputs one line per procedure
-$0 --web /bin/ls ls.prof
- Displays annotated call-graph in web browser
-$0 --gv /bin/ls ls.prof
- Displays annotated call-graph via 'gv'
-$0 --gv --focus=Mutex /bin/ls ls.prof
- Restricts to code paths including a .*Mutex.* entry
-$0 --gv --focus=Mutex --ignore=string /bin/ls ls.prof
- Code paths including Mutex but not string
-$0 --list=getdir /bin/ls ls.prof
- (Per-line) annotated source listing for getdir()
-$0 --disasm=getdir /bin/ls ls.prof
- (Per-PC) annotated disassembly for getdir()
-
-$0 http://localhost:1234/
- Enters "interactive" mode
-$0 --text localhost:1234
- Outputs one line per procedure for localhost:1234
-$0 --raw localhost:1234 > ./local.raw
-$0 --text ./local.raw
- Fetches a remote profile for later analysis and then
- analyzes it in text mode.
-EOF
-}
-
-sub version_string {
- return <<EOF
-pprof (part of gperftools $PPROF_VERSION)
-
-Copyright 1998-2007 Google Inc.
-
-This is BSD licensed software; see the source for copying conditions
-and license information.
-There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE.
-EOF
-}
-
-sub usage {
- my $msg = shift;
- print STDERR "$msg\n\n";
- print STDERR usage_string();
- exit(1);
-}
-
-sub Init() {
- # Setup tmp-file name and handler to clean it up.
- # We do this in the very beginning so that we can use
- # error() and cleanup() function anytime here after.
- $main::tmpfile_sym = "/tmp/pprof$$.sym";
- $main::tmpfile_ps = "/tmp/pprof$$";
- $main::next_tmpfile = 0;
- $SIG{'INT'} = \&sighandler;
-
- # Cache from filename/linenumber to source code
- $main::source_cache = ();
-
- $main::opt_help = 0;
- $main::opt_version = 0;
- $main::opt_show_addresses = 0;
- $main::opt_no_auto_signal_frames = 0;
-
- $main::opt_cum = 0;
- $main::opt_base = '';
- $main::opt_addresses = 0;
- $main::opt_lines = 0;
- $main::opt_functions = 0;
- $main::opt_files = 0;
- $main::opt_lib_prefix = "";
-
- $main::opt_text = 0;
- $main::opt_stacks = 0;
- $main::opt_callgrind = 0;
- $main::opt_list = "";
- $main::opt_disasm = "";
- $main::opt_symbols = 0;
- $main::opt_gv = 0;
- $main::opt_evince = 0;
- $main::opt_web = 0;
- $main::opt_dot = 0;
- $main::opt_ps = 0;
- $main::opt_pdf = 0;
- $main::opt_gif = 0;
- $main::opt_svg = 0;
- $main::opt_raw = 0;
- $main::opt_collapsed = 0;
-
- $main::opt_nodecount = 80;
- $main::opt_nodefraction = 0.005;
- $main::opt_edgefraction = 0.001;
- $main::opt_maxdegree = 8;
- $main::opt_focus = '';
- $main::opt_ignore = '';
- $main::opt_scale = 0;
- $main::opt_heapcheck = 0;
- $main::opt_seconds = 30;
- $main::opt_lib = "";
-
- $main::opt_inuse_space = 0;
- $main::opt_inuse_objects = 0;
- $main::opt_alloc_space = 0;
- $main::opt_alloc_objects = 0;
- $main::opt_show_bytes = 0;
- $main::opt_drop_negative = 0;
- $main::opt_interactive = 0;
-
- $main::opt_total_delay = 0;
- $main::opt_contentions = 0;
- $main::opt_mean_delay = 0;
-
- $main::opt_tools = "";
- $main::opt_debug = 0;
- $main::opt_test = 0;
-
- # Do not strip template argument in function names
- $main::opt_no_strip_temp = 0;
-
- # These are undocumented flags used only by unittests.
- $main::opt_test_stride = 0;
-
- # Are we using $SYMBOL_PAGE?
- $main::use_symbol_page = 0;
-
- # Files returned by TempName.
- %main::tempnames = ();
-
- # Type of profile we are dealing with
- # Supported types:
- # cpu
- # heap
- # growth
- # contention
- $main::profile_type = ''; # Empty type means "unknown"
-
- GetOptions("help!" => \$main::opt_help,
- "version!" => \$main::opt_version,
- "show_addresses!"=> \$main::opt_show_addresses,
- "no-auto-signal-frm!"=> \$main::opt_no_auto_signal_frames,
- "cum!" => \$main::opt_cum,
- "base=s" => \$main::opt_base,
- "seconds=i" => \$main::opt_seconds,
- "add_lib=s" => \$main::opt_lib,
- "lib_prefix=s" => \$main::opt_lib_prefix,
- "functions!" => \$main::opt_functions,
- "lines!" => \$main::opt_lines,
- "addresses!" => \$main::opt_addresses,
- "files!" => \$main::opt_files,
- "text!" => \$main::opt_text,
- "stacks!" => \$main::opt_stacks,
- "callgrind!" => \$main::opt_callgrind,
- "list=s" => \$main::opt_list,
- "disasm=s" => \$main::opt_disasm,
- "symbols!" => \$main::opt_symbols,
- "gv!" => \$main::opt_gv,
- "evince!" => \$main::opt_evince,
- "web!" => \$main::opt_web,
- "dot!" => \$main::opt_dot,
- "ps!" => \$main::opt_ps,
- "pdf!" => \$main::opt_pdf,
- "svg!" => \$main::opt_svg,
- "gif!" => \$main::opt_gif,
- "raw!" => \$main::opt_raw,
- "collapsed!" => \$main::opt_collapsed,
- "interactive!" => \$main::opt_interactive,
- "nodecount=i" => \$main::opt_nodecount,
- "nodefraction=f" => \$main::opt_nodefraction,
- "edgefraction=f" => \$main::opt_edgefraction,
- "maxdegree=i" => \$main::opt_maxdegree,
- "focus=s" => \$main::opt_focus,
- "ignore=s" => \$main::opt_ignore,
- "scale=i" => \$main::opt_scale,
- "heapcheck" => \$main::opt_heapcheck,
- "inuse_space!" => \$main::opt_inuse_space,
- "inuse_objects!" => \$main::opt_inuse_objects,
- "alloc_space!" => \$main::opt_alloc_space,
- "alloc_objects!" => \$main::opt_alloc_objects,
- "show_bytes!" => \$main::opt_show_bytes,
- "drop_negative!" => \$main::opt_drop_negative,
- "total_delay!" => \$main::opt_total_delay,
- "contentions!" => \$main::opt_contentions,
- "mean_delay!" => \$main::opt_mean_delay,
- "tools=s" => \$main::opt_tools,
- "no_strip_temp!" => \$main::opt_no_strip_temp,
- "test!" => \$main::opt_test,
- "debug!" => \$main::opt_debug,
- # Undocumented flags used only by unittests:
- "test_stride=i" => \$main::opt_test_stride,
- ) || usage("Invalid option(s)");
-
- # Deal with the standard --help and --version
- if ($main::opt_help) {
- print usage_string();
- exit(0);
- }
-
- if ($main::opt_version) {
- print version_string();
- exit(0);
- }
-
- # Disassembly/listing/symbols mode requires address-level info
- if ($main::opt_disasm || $main::opt_list || $main::opt_symbols) {
- $main::opt_functions = 0;
- $main::opt_lines = 0;
- $main::opt_addresses = 1;
- $main::opt_files = 0;
- }
-
- # Check heap-profiling flags
- if ($main::opt_inuse_space +
- $main::opt_inuse_objects +
- $main::opt_alloc_space +
- $main::opt_alloc_objects > 1) {
- usage("Specify at most on of --inuse/--alloc options");
- }
-
- # Check output granularities
- my $grains =
- $main::opt_functions +
- $main::opt_lines +
- $main::opt_addresses +
- $main::opt_files +
- 0;
- if ($grains > 1) {
- usage("Only specify one output granularity option");
- }
- if ($grains == 0) {
- $main::opt_functions = 1;
- }
-
- # Check output modes
- my $modes =
- $main::opt_text +
- $main::opt_callgrind +
- ($main::opt_list eq '' ? 0 : 1) +
- ($main::opt_disasm eq '' ? 0 : 1) +
- ($main::opt_symbols == 0 ? 0 : 1) +
- $main::opt_gv +
- $main::opt_evince +
- $main::opt_web +
- $main::opt_dot +
- $main::opt_ps +
- $main::opt_pdf +
- $main::opt_svg +
- $main::opt_gif +
- $main::opt_raw +
- $main::opt_collapsed +
- $main::opt_interactive +
- 0;
- if ($modes > 1) {
- usage("Only specify one output mode");
- }
- if ($modes == 0) {
- if (-t STDOUT) { # If STDOUT is a tty, activate interactive mode
- $main::opt_interactive = 1;
- } else {
- $main::opt_text = 1;
- }
- }
-
- if ($main::opt_test) {
- RunUnitTests();
- # Should not return
- exit(1);
- }
-
- # Binary name and profile arguments list
- $main::prog = "";
- @main::pfile_args = ();
-
- # Remote profiling without a binary (using $SYMBOL_PAGE instead)
- if (@ARGV > 0) {
- if (IsProfileURL($ARGV[0])) {
- printf STDERR "Using remote profile at $ARGV[0].\n";
- $main::use_symbol_page = 1;
- } elsif (IsSymbolizedProfileFile($ARGV[0])) {
- $main::use_symbolized_profile = 1;
- $main::prog = $UNKNOWN_BINARY; # will be set later from the profile file
- }
- }
-
- if ($main::use_symbol_page || $main::use_symbolized_profile) {
- # We don't need a binary!
- my %disabled = ('--lines' => $main::opt_lines,
- '--disasm' => $main::opt_disasm);
- for my $option (keys %disabled) {
- usage("$option cannot be used without a binary") if $disabled{$option};
- }
- # Set $main::prog later...
- scalar(@ARGV) || usage("Did not specify profile file");
- } elsif ($main::opt_symbols) {
- # --symbols needs a binary-name (to run nm on, etc) but not profiles
- $main::prog = shift(@ARGV) || usage("Did not specify program");
- } else {
- $main::prog = shift(@ARGV) || usage("Did not specify program");
- scalar(@ARGV) || usage("Did not specify profile file");
- }
-
- # Parse profile file/location arguments
- foreach my $farg (@ARGV) {
- if ($farg =~ m/(.*)\@([0-9]+)(|\/.*)$/ ) {
- my $machine = $1;
- my $num_machines = $2;
- my $path = $3;
- for (my $i = 0; $i < $num_machines; $i++) {
- unshift(@main::pfile_args, "$i.$machine$path");
- }
- } else {
- unshift(@main::pfile_args, $farg);
- }
- }
-
- if ($main::use_symbol_page) {
- unless (IsProfileURL($main::pfile_args[0])) {
- error("The first profile should be a remote form to use $SYMBOL_PAGE\n");
- }
- CheckSymbolPage();
- $main::prog = FetchProgramName();
- } elsif (!$main::use_symbolized_profile) { # may not need objtools!
- ConfigureObjTools($main::prog)
- }
-
- # 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
- # searching things like /my/path//lib/mylib.so
- foreach (@prefix_list) {
- s|/+$||;
- }
-}
-
-sub Main() {
- Init();
- $main::collected_profile = undef;
- @main::profile_files = ();
- $main::op_time = time();
-
- # Printing symbols is special and requires a lot less info that most.
- if ($main::opt_symbols) {
- PrintSymbols(*STDIN); # Get /proc/maps and symbols output from stdin
- return;
- }
-
- # Fetch all profile data
- FetchDynamicProfiles();
-
- # this will hold symbols that we read from the profile files
- my $symbol_map = {};
-
- # Read one profile, pick the last item on the list
- my $data = ReadProfile($main::prog, pop(@main::profile_files));
- my $profile = $data->{profile};
- my $pcs = $data->{pcs};
- my $libs = $data->{libs}; # Info about main program and shared libraries
- $symbol_map = MergeSymbols($symbol_map, $data->{symbols});
-
- # Add additional profiles, if available.
- if (scalar(@main::profile_files) > 0) {
- foreach my $pname (@main::profile_files) {
- my $data2 = ReadProfile($main::prog, $pname);
- $profile = AddProfile($profile, $data2->{profile});
- $pcs = AddPcs($pcs, $data2->{pcs});
- $symbol_map = MergeSymbols($symbol_map, $data2->{symbols});
- }
- }
-
- # Subtract base from profile, if specified
- if ($main::opt_base ne '') {
- my $base = ReadProfile($main::prog, $main::opt_base);
- $profile = SubtractProfile($profile, $base->{profile});
- $pcs = AddPcs($pcs, $base->{pcs});
- $symbol_map = MergeSymbols($symbol_map, $base->{symbols});
- }
-
- # Get total data in profile
- my $total = TotalProfile($profile);
-
- # Collect symbols
- my $symbols;
- if ($main::use_symbolized_profile) {
- $symbols = FetchSymbols($pcs, $symbol_map);
- } elsif ($main::use_symbol_page) {
- $symbols = FetchSymbols($pcs);
- } else {
- # TODO(csilvers): $libs uses the /proc/self/maps data from profile1,
- # which may differ from the data from subsequent profiles, especially
- # if they were run on different machines. Use appropriate libs for
- # each pc somehow.
- $symbols = ExtractSymbols($libs, $pcs);
- }
-
- # Remove uniniteresting stack items
- $profile = RemoveUninterestingFrames($symbols, $profile);
-
- # Focus?
- if ($main::opt_focus ne '') {
- $profile = FocusProfile($symbols, $profile, $main::opt_focus);
- }
-
- # Ignore?
- if ($main::opt_ignore ne '') {
- $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore);
- }
-
- my $calls = ExtractCalls($symbols, $profile);
-
- # Reduce profiles to required output granularity, and also clean
- # each stack trace so a given entry exists at most once.
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- # Print
- if (!$main::opt_interactive) {
- if ($main::opt_disasm) {
- PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm);
- } elsif ($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
- # compatible with old branches that did not pass --heapcheck always):
- if ($total != 0) {
- printf("Total: %s %s\n", Unparse($total), Units());
- }
- if ($main::opt_stacks) {
- printf("Stacks:\n\n");
- PrintStacksForText($symbols, $profile);
- }
- PrintText($symbols, $flat, $cumulative, -1);
- } elsif ($main::opt_raw) {
- PrintSymbolizedProfile($symbols, $profile, $main::prog);
- } elsif ($main::opt_collapsed) {
- PrintCollapsedStacks($symbols, $profile);
- } elsif ($main::opt_callgrind) {
- PrintCallgrind($calls);
- } else {
- if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
- if ($main::opt_gv) {
- RunGV(TempName($main::next_tmpfile, "ps"), "");
- } elsif ($main::opt_evince) {
- RunEvince(TempName($main::next_tmpfile, "pdf"), "");
- } elsif ($main::opt_web) {
- my $tmp = TempName($main::next_tmpfile, "svg");
- RunWeb($tmp);
- # The command we run might hand the file name off
- # to an already running browser instance and then exit.
- # Normally, we'd remove $tmp on exit (right now),
- # but fork a child to remove $tmp a little later, so that the
- # browser has time to load it first.
- delete $main::tempnames{$tmp};
- if (fork() == 0) {
- sleep 5;
- unlink($tmp);
- exit(0);
- }
- }
- } else {
- cleanup();
- exit(1);
- }
- }
- } else {
- InteractiveMode($profile, $symbols, $libs, $total);
- }
-
- cleanup();
- exit(0);
-}
-
-##### Entry Point #####
-
-Main();
-
-# Temporary code to detect if we're running on a Goobuntu system.
-# These systems don't have the right stuff installed for the special
-# Readline libraries to work, so as a temporary workaround, we default
-# to using the normal stdio code, rather than the fancier readline-based
-# code
-sub ReadlineMightFail {
- if (-e '/lib/libtermcap.so.2') {
- return 0; # libtermcap exists, so readline should be okay
- } else {
- return 1;
- }
-}
-
-sub RunGV {
- my $fname = shift;
- my $bg = shift; # "" or " &" if we should run in background
- if (!system(ShellEscape(@GV, "--version") . " >$dev_null 2>&1")) {
- # Options using double dash are supported by this gv version.
- # Also, turn on noantialias to better handle bug in gv for
- # postscript files with large dimensions.
- # TODO: Maybe we should not pass the --noantialias flag
- # if the gv version is known to work properly without the flag.
- system(ShellEscape(@GV, "--scale=$main::opt_scale", "--noantialias", $fname)
- . $bg);
- } else {
- # Old gv version - only supports options that use single dash.
- print STDERR ShellEscape(@GV, "-scale", $main::opt_scale) . "\n";
- system(ShellEscape(@GV, "-scale", "$main::opt_scale", $fname) . $bg);
- }
-}
-
-sub RunEvince {
- my $fname = shift;
- my $bg = shift; # "" or " &" if we should run in background
- system(ShellEscape(@EVINCE, $fname) . $bg);
-}
-
-sub RunWeb {
- my $fname = shift;
- print STDERR "Loading web page file:///$fname\n";
-
- if (`uname` =~ /Darwin/) {
- # OS X: open will use standard preference for SVG files.
- system("/usr/bin/open", $fname);
- return;
- }
-
- if (`uname` =~ /MINGW/) {
- # Windows(MinGW): open will use standard preference for SVG files.
- system("cmd", "/c", "start", $fname);
- return;
- }
-
- # Some kind of Unix; try generic symlinks, then specific browsers.
- # (Stop once we find one.)
- # Works best if the browser is already running.
- my @alt = (
- "/etc/alternatives/gnome-www-browser",
- "/etc/alternatives/x-www-browser",
- "google-chrome",
- "firefox",
- );
- foreach my $b (@alt) {
- if (system($b, $fname) == 0) {
- return;
- }
- }
-
- print STDERR "Could not load web browser.\n";
-}
-
-sub RunKcachegrind {
- my $fname = shift;
- my $bg = shift; # "" or " &" if we should run in background
- print STDERR "Starting '@KCACHEGRIND " . $fname . $bg . "'\n";
- system(ShellEscape(@KCACHEGRIND, $fname) . $bg);
-}
-
-
-##### Interactive helper routines #####
-
-sub InteractiveMode {
- $| = 1; # Make output unbuffered for interactive mode
- my ($orig_profile, $symbols, $libs, $total) = @_;
-
- print STDERR "Welcome to pprof! For help, type 'help'.\n";
-
- # Use ReadLine if it's installed and input comes from a console.
- if ( -t STDIN &&
- !ReadlineMightFail() &&
- defined(eval {require Term::ReadLine}) ) {
- my $term = new Term::ReadLine 'pprof';
- while ( defined ($_ = $term->readline('(pprof) '))) {
- $term->addhistory($_) if /\S/;
- if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {
- last; # exit when we get an interactive command to quit
- }
- }
- } else { # don't have readline
- while (1) {
- print STDERR "(pprof) ";
- $_ = <STDIN>;
- last if ! defined $_ ;
- s/\r//g; # turn windows-looking lines into unix-looking lines
-
- # Save some flags that might be reset by InteractiveCommand()
- my $save_opt_lines = $main::opt_lines;
-
- if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {
- last; # exit when we get an interactive command to quit
- }
-
- # Restore flags
- $main::opt_lines = $save_opt_lines;
- }
- }
-}
-
-# Takes two args: orig profile, and command to run.
-# Returns 1 if we should keep going, or 0 if we were asked to quit
-sub InteractiveCommand {
- my($orig_profile, $symbols, $libs, $total, $command) = @_;
- $_ = $command; # just to make future m//'s easier
- if (!defined($_)) {
- print STDERR "\n";
- return 0;
- }
- if (m/^\s*quit/) {
- return 0;
- }
- if (m/^\s*help/) {
- InteractiveHelpMessage();
- return 1;
- }
- # Clear all the mode options -- mode is controlled by "$command"
- $main::opt_text = 0;
- $main::opt_callgrind = 0;
- $main::opt_disasm = 0;
- $main::opt_list = 0;
- $main::opt_gv = 0;
- $main::opt_evince = 0;
- $main::opt_cum = 0;
-
- if (m/^\s*(text|top)(\d*)\s*(.*)/) {
- $main::opt_text = 1;
-
- my $line_limit = ($2 ne "") ? int($2) : 10;
-
- my $routine;
- my $ignore;
- ($routine, $ignore) = ParseInteractiveArgs($3);
-
- my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- PrintText($symbols, $flat, $cumulative, $line_limit);
- return 1;
- }
- if (m/^\s*callgrind\s*([^ \n]*)/) {
- $main::opt_callgrind = 1;
-
- # Get derived profiles
- my $calls = ExtractCalls($symbols, $orig_profile);
- my $filename = $1;
- if ( $1 eq '' ) {
- $filename = TempName($main::next_tmpfile, "callgrind");
- }
- PrintCallgrind($calls, $filename);
- if ( $1 eq '' ) {
- RunKcachegrind($filename, " & ");
- $main::next_tmpfile++;
- }
-
- return 1;
- }
- if (m/^\s*(web)?list\s*(.+)/) {
- my $html = (defined($1) && ($1 eq "web"));
- $main::opt_list = 1;
-
- my $routine;
- my $ignore;
- ($routine, $ignore) = ParseInteractiveArgs($2);
-
- 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($total, $libs, $flat, $cumulative, $routine, $html);
- return 1;
- }
- if (m/^\s*disasm\s*(.+)/) {
- $main::opt_disasm = 1;
-
- my $routine;
- my $ignore;
- ($routine, $ignore) = ParseInteractiveArgs($1);
-
- # Process current profile to account for various settings
- my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- PrintDisassembly($libs, $flat, $cumulative, $routine);
- return 1;
- }
- if (m/^\s*(gv|web|evince)\s*(.*)/) {
- $main::opt_gv = 0;
- $main::opt_evince = 0;
- $main::opt_web = 0;
- if ($1 eq "gv") {
- $main::opt_gv = 1;
- } elsif ($1 eq "evince") {
- $main::opt_evince = 1;
- } elsif ($1 eq "web") {
- $main::opt_web = 1;
- }
-
- my $focus;
- my $ignore;
- ($focus, $ignore) = ParseInteractiveArgs($2);
-
- # Process current profile to account for various settings
- my $profile = ProcessProfile($total, $orig_profile, $symbols,
- $focus, $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
- if ($main::opt_gv) {
- RunGV(TempName($main::next_tmpfile, "ps"), " &");
- } elsif ($main::opt_evince) {
- RunEvince(TempName($main::next_tmpfile, "pdf"), " &");
- } elsif ($main::opt_web) {
- RunWeb(TempName($main::next_tmpfile, "svg"));
- }
- $main::next_tmpfile++;
- }
- return 1;
- }
- if (m/^\s*$/) {
- return 1;
- }
- print STDERR "Unknown command: try 'help'.\n";
- return 1;
-}
-
-
-sub ProcessProfile {
- my $total_count = shift;
- my $orig_profile = shift;
- my $symbols = shift;
- my $focus = shift;
- my $ignore = shift;
-
- # Process current profile to account for various settings
- my $profile = $orig_profile;
- printf("Total: %s %s\n", Unparse($total_count), Units());
- if ($focus ne '') {
- $profile = FocusProfile($symbols, $profile, $focus);
- my $focus_count = TotalProfile($profile);
- printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n",
- $focus,
- Unparse($focus_count), Units(),
- Unparse($total_count), ($focus_count*100.0) / $total_count);
- }
- if ($ignore ne '') {
- $profile = IgnoreProfile($symbols, $profile, $ignore);
- my $ignore_count = TotalProfile($profile);
- printf("After ignoring '%s': %s %s of %s (%0.1f%%)\n",
- $ignore,
- Unparse($ignore_count), Units(),
- Unparse($total_count),
- ($ignore_count*100.0) / $total_count);
- }
-
- return $profile;
-}
-
-sub InteractiveHelpMessage {
- print STDERR <<ENDOFHELP;
-Interactive pprof mode
-
-Commands:
- gv
- gv [focus] [-ignore1] [-ignore2]
- Show graphical hierarchical display of current profile. Without
- any arguments, shows all samples in the profile. With the optional
- "focus" argument, restricts the samples shown to just those where
- the "focus" regular expression matches a routine name on the stack
- trace.
-
- web
- web [focus] [-ignore1] [-ignore2]
- Like GV, but displays profile in your web browser instead of using
- Ghostview. Works best if your web browser is already running.
- To change the browser that gets used:
- On Linux, set the /etc/alternatives/gnome-www-browser symlink.
- On OS X, change the Finder association for SVG files.
-
- 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]
- Show top lines ordered by flat profile count, or cumulative count
- if --cum is specified. If a number is present after 'top', the
- top K routines will be shown (defaults to showing the top 10)
-
- disasm [routine_regexp] [-ignore1] [-ignore2]
- Show disassembly of routines whose names match "routine_regexp",
- annotated with sample counts.
-
- callgrind
- callgrind [filename]
- Generates callgrind file. If no filename is given, kcachegrind is called.
-
- help - This listing
- quit or ^D - End pprof
-
-For commands that accept optional -ignore tags, samples where any routine in
-the stack trace matches the regular expression in any of the -ignore
-parameters will be ignored.
-
-Further pprof details are available at this location (or one similar):
-
- /usr/doc/gperftools-$PPROF_VERSION/cpu_profiler.html
- /usr/doc/gperftools-$PPROF_VERSION/heap_profiler.html
-
-ENDOFHELP
-}
-sub ParseInteractiveArgs {
- my $args = shift;
- my $focus = "";
- my $ignore = "";
- my @x = split(/ +/, $args);
- foreach $a (@x) {
- if ($a =~ m/^(--|-)lines$/) {
- $main::opt_lines = 1;
- } elsif ($a =~ m/^(--|-)cum$/) {
- $main::opt_cum = 1;
- } elsif ($a =~ m/^-(.*)/) {
- $ignore .= (($ignore ne "") ? "|" : "" ) . $1;
- } else {
- $focus .= (($focus ne "") ? "|" : "" ) . $a;
- }
- }
- if ($ignore ne "") {
- print STDERR "Ignoring samples in call stacks that match '$ignore'\n";
- }
- return ($focus, $ignore);
-}
-
-##### Output code #####
-
-sub TempName {
- my $fnum = shift;
- my $ext = shift;
- my $file = "$main::tmpfile_ps.$fnum.$ext";
- $main::tempnames{$file} = 1;
- return $file;
-}
-
-# Print profile data in packed binary format (64-bit) to standard out
-sub PrintProfileData {
- my $profile = shift;
- my $big_endian = pack("L", 1) eq pack("N", 1);
- # print header (64-bit style)
- # (zero) (header-size) (version) (sample-period) (zero)
- if ($big_endian) {
- print pack('L*', 0, 0, 0, 3, 0, 0, 0, 1, 0, 0);
- }
- else {
- print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0);
- }
-
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- if ($#addrs >= 0) {
- my $depth = $#addrs + 1;
- # int(foo / 2**32) is the only reliable way to get rid of bottom
- # 32 bits on both 32- and 64-bit systems.
- if ($big_endian) {
- print pack('L*', int($count / 2**32), $count & 0xFFFFFFFF);
- print pack('L*', int($depth / 2**32), $depth & 0xFFFFFFFF);
- }
- else {
- print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32));
- print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32));
- }
-
- foreach my $full_addr (@addrs) {
- my $addr = $full_addr;
- $addr =~ s/0x0*//; # strip off leading 0x, zeroes
- if (length($addr) > 16) {
- print STDERR "Invalid address in profile: $full_addr\n";
- next;
- }
- my $low_addr = substr($addr, -8); # get last 8 hex chars
- my $high_addr = substr($addr, -16, 8); # get up to 8 more hex chars
- if ($big_endian) {
- print pack('L*', hex('0x' . $high_addr), hex('0x' . $low_addr));
- }
- else {
- print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr));
- }
- }
- }
- }
-}
-
-# Print symbols and profile data
-sub PrintSymbolizedProfile {
- my $symbols = shift;
- my $profile = shift;
- my $prog = shift;
-
- $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $symbol_marker = $&;
-
- print '--- ', $symbol_marker, "\n";
- if (defined($prog)) {
- print 'binary=', $prog, "\n";
- }
- while (my ($pc, $name) = each(%{$symbols})) {
- my $sep = ' ';
- print '0x', $pc;
- # We have a list of function names, which include the inlined
- # calls. They are separated (and terminated) by --, which is
- # illegal in function names.
- for (my $j = 2; $j <= $#{$name}; $j += 3) {
- print $sep, $name->[$j];
- $sep = '--';
- }
- print "\n";
- }
- print '---', "\n";
-
- $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $profile_marker = $&;
- print '--- ', $profile_marker, "\n";
- if (defined($main::collected_profile)) {
- # if used with remote fetch, simply dump the collected profile to output.
- open(SRC, "<$main::collected_profile");
- while (<SRC>) {
- print $_;
- }
- close(SRC);
- } else {
- # dump a cpu-format profile to standard out
- PrintProfileData($profile);
- }
-}
-
-# Print text output
-sub PrintText {
- my $symbols = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $line_limit = shift;
-
- if ($main::opt_stacks && @stackTraces) {
- foreach (sort { (split " ", $b)[1] <=> (split " ", $a)[1]; } @stackTraces) {
- print "$_\n" if $main::opt_debug;
- my ($n1, $s1, $n2, $s2, @addrs) = split;
- print "Leak of $s1 bytes in $n1 objects allocated from:\n";
- foreach my $pcstr (@addrs) {
- $pcstr =~ s/^0x//;
- my $sym;
- if (! defined $symbols->{$pcstr}) {
- $sym = "unknown";
- } else {
- $sym = "$symbols->{$pcstr}[0] $symbols->{$pcstr}[1]";
- }
- print "\t@ $pcstr $sym\n";
- }
- }
- print "\n";
- }
-
- my $total = TotalProfile($flat);
-
- # Which profile to sort by?
- my $s = $main::opt_cum ? $cumulative : $flat;
-
- my $running_sum = 0;
- my $lines = 0;
- foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b }
- keys(%{$cumulative})) {
- my $f = GetEntry($flat, $k);
- my $c = GetEntry($cumulative, $k);
- $running_sum += $f;
-
- my $sym = $k;
- if (exists($symbols->{$k})) {
- $sym = $symbols->{$k}->[0] . " " . $symbols->{$k}->[1];
- if ($main::opt_addresses) {
- $sym = $k . " " . $sym;
- }
- }
-
- if ($f != 0 || $c != 0) {
- printf("%8s %6s %6s %8s %6s %s\n",
- Unparse($f),
- Percent($f, $total),
- Percent($running_sum, $total),
- Unparse($c),
- Percent($c, $total),
- $sym);
- }
- $lines++;
- last if ($line_limit >= 0 && $lines >= $line_limit);
- }
-}
-
-# Callgrind format has a compression for repeated function and file
-# names. You show the name the first time, and just use its number
-# subsequently. This can cut down the file to about a third or a
-# quarter of its uncompressed size. $key and $val are the key/value
-# pair that would normally be printed by callgrind; $map is a map from
-# value to number.
-sub CompressedCGName {
- my($key, $val, $map) = @_;
- my $idx = $map->{$val};
- # For very short keys, providing an index hurts rather than helps.
- if (length($val) <= 3) {
- return "$key=$val\n";
- } elsif (defined($idx)) {
- return "$key=($idx)\n";
- } else {
- # scalar(keys $map) gives the number of items in the map.
- $idx = scalar(keys(%{$map})) + 1;
- $map->{$val} = $idx;
- return "$key=($idx) $val\n";
- }
-}
-
-# Print the call graph in a way that's suiteable for callgrind.
-sub PrintCallgrind {
- my $calls = shift;
- my $filename;
- my %filename_to_index_map;
- my %fnname_to_index_map;
-
- if ($main::opt_interactive) {
- $filename = shift;
- print STDERR "Writing callgrind file to '$filename'.\n"
- } else {
- $filename = "&STDOUT";
- }
- open(CG, ">$filename");
- print CG ("events: Hits\n\n");
- foreach my $call ( map { $_->[0] }
- sort { $a->[1] cmp $b ->[1] ||
- $a->[2] <=> $b->[2] }
- map { /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/;
- [$_, $1, $2] }
- keys %$calls ) {
- my $count = int($calls->{$call});
- $call =~ /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/;
- my ( $caller_file, $caller_line, $caller_function,
- $callee_file, $callee_line, $callee_function ) =
- ( $1, $2, $3, $5, $6, $7 );
-
- # TODO(csilvers): for better compression, collect all the
- # caller/callee_files and functions first, before printing
- # anything, and only compress those referenced more than once.
- print CG CompressedCGName("fl", $caller_file, \%filename_to_index_map);
- print CG CompressedCGName("fn", $caller_function, \%fnname_to_index_map);
- if (defined $6) {
- print CG CompressedCGName("cfl", $callee_file, \%filename_to_index_map);
- print CG CompressedCGName("cfn", $callee_function, \%fnname_to_index_map);
- print CG ("calls=$count $callee_line\n");
- }
- print CG ("$caller_line $count\n\n");
- }
-}
-
-# Print disassembly for all all routines that match $main::opt_disasm
-sub PrintDisassembly {
- my $libs = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $disasm_opts = shift;
-
- my $total = TotalProfile($flat);
-
- foreach my $lib (@{$libs}) {
- my $symbol_table = GetProcedureBoundaries($lib->[0], $disasm_opts);
- my $offset = AddressSub($lib->[1], $lib->[3]);
- foreach my $routine (sort ByName keys(%{$symbol_table})) {
- my $start_addr = $symbol_table->{$routine}->[0];
- my $end_addr = $symbol_table->{$routine}->[1];
- # See if there are any samples in this routine
- my $length = hex(AddressSub($end_addr, $start_addr));
- my $addr = AddressAdd($start_addr, $offset);
- for (my $i = 0; $i < $length; $i++) {
- if (defined($cumulative->{$addr})) {
- PrintDisassembledFunction($lib->[0], $offset,
- $routine, $flat, $cumulative,
- $start_addr, $end_addr, $total);
- last;
- }
- $addr = AddressInc($addr);
- }
- }
- }
-}
-
-# Return reference to array of tuples of the form:
-# [start_address, filename, linenumber, instruction, limit_address]
-# E.g.,
-# ["0x806c43d", "/foo/bar.cc", 131, "ret", "0x806c440"]
-sub Disassemble {
- my $prog = shift;
- my $offset = shift;
- my $start_addr = shift;
- my $end_addr = shift;
-
- my $objdump = $obj_tool_map{"objdump"};
- my $cmd = ShellEscape($objdump, "-C", "-d", "-l", "--no-show-raw-insn",
- "--start-address=0x$start_addr",
- "--stop-address=0x$end_addr", $prog);
- open(OBJDUMP, "$cmd |") || error("$cmd: $!\n");
- my @result = ();
- my $filename = "";
- my $linenumber = -1;
- my $last = ["", "", "", ""];
- while (<OBJDUMP>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- chop;
- if (m|\s*([^:\s]+):(\d+)\s*$|) {
- # Location line of the form:
- # <filename>:<linenumber>
- $filename = $1;
- $linenumber = $2;
- } elsif (m/^ +([0-9a-f]+):\s*(.*)/) {
- # Disassembly line -- zero-extend address to full length
- my $addr = HexExtend($1);
- my $k = AddressAdd($addr, $offset);
- $last->[4] = $k; # Store ending address for previous instruction
- $last = [$k, $filename, $linenumber, $2, $end_addr];
- push(@result, $last);
- }
- }
- close(OBJDUMP);
- return @result;
-}
-
-# The input file should contain lines of the form /proc/maps-like
-# output (same format as expected from the profiles) or that looks
-# like hex addresses (like "0xDEADBEEF"). We will parse all
-# /proc/maps output, and for all the hex addresses, we will output
-# "short" symbol names, one per line, in the same order as the input.
-sub PrintSymbols {
- my $maps_and_symbols_file = shift;
-
- # ParseLibraries expects pcs to be in a set. Fine by us...
- my @pclist = (); # pcs in sorted order
- my $pcs = {};
- my $map = "";
- foreach my $line (<$maps_and_symbols_file>) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- if ($line =~ /\b(0x[0-9a-f]+)\b/i) {
- push(@pclist, HexExtend($1));
- $pcs->{$pclist[-1]} = 1;
- } else {
- $map .= $line;
- }
- }
-
- my $libs = ParseLibraries($main::prog, $map, $pcs);
- my $symbols = ExtractSymbols($libs, $pcs);
-
- foreach my $pc (@pclist) {
- # ->[0] is the shortname, ->[2] is the full name
- print(($symbols->{$pc}->[0] || "??") . "\n");
- }
-}
-
-
-# For sorting functions by name
-sub ByName {
- return ShortFunctionName($a) cmp ShortFunctionName($b);
-}
-
-# 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]);
- foreach my $routine (sort ByName keys(%{$symbol_table})) {
- # Print if there are any samples in this routine
- my $start_addr = $symbol_table->{$routine}->[0];
- my $end_addr = $symbol_table->{$routine}->[1];
- my $length = hex(AddressSub($end_addr, $start_addr));
- my $addr = AddressAdd($start_addr, $offset);
- for (my $i = 0; $i < $length; $i++) {
- if (defined($cumulative->{$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/&/&amp;/g;
- $text =~ s/</&lt;/g;
- $text =~ s/>/&gt;/g;
- return $text;
-}
-
-# Returns the indentation of the line, if it has any non-whitespace
-# characters. Otherwise, returns -1.
-sub Indentation {
- my $line = shift;
- if (m/^(\s*)\S/) {
- return length($1);
- } else {
- return -1;
- }
-}
-
-# 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;
- my $offset = shift;
- my $routine = shift;
- my $flat = shift;
- 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
- my $filename = undef;
- for (my $i = 0; $i <= $#instructions; $i++) {
- if ($instructions[$i]->[2] >= 0) {
- $filename = $instructions[$i]->[1];
- last;
- }
- }
- if (!defined($filename)) {
- print STDERR "no filename found in $routine\n";
- return 0;
- }
-
- # Hack 2: assume that the largest line number from $filename is the
- # end of the procedure. This is typically safe since if P1 contains
- # an inlined call to P2, then P2 usually occurs earlier in the
- # source file. If this does not work, we might have to compute a
- # density profile or just print all regions we find.
- my $lastline = 0;
- for (my $i = 0; $i <= $#instructions; $i++) {
- my $f = $instructions[$i]->[1];
- my $l = $instructions[$i]->[2];
- if (($f eq $filename) && ($l > $lastline)) {
- $lastline = $l;
- }
- }
-
- # Hack 3: assume the first source location from "filename" is the start of
- # the source code.
- my $firstline = 1;
- for (my $i = 0; $i <= $#instructions; $i++) {
- if ($instructions[$i]->[1] eq $filename) {
- $firstline = $instructions[$i]->[2];
- last;
- }
- }
-
- # Hack 4: Extend last line forward until its indentation is less than
- # the indentation we saw on $firstline
- my $oldlastline = $lastline;
- {
- if (!open(FILE, "<$filename")) {
- print STDERR "$filename: $!\n";
- return 0;
- }
- my $l = 0;
- my $first_indentation = -1;
- while (<FILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $l++;
- my $indent = Indentation($_);
- if ($l >= $firstline) {
- if ($first_indentation < 0 && $indent >= 0) {
- $first_indentation = $indent;
- last if ($first_indentation == 0);
- }
- }
- if ($l >= $lastline && $indent >= 0) {
- if ($indent >= $first_indentation) {
- $lastline = $l+1;
- } else {
- last;
- }
- }
- }
- close(FILE);
- }
-
- # 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 = {}; # 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;
- my $c2 = 0;
- for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {
- $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;
- $total2 += $c2;
- my $file = $e->[1];
- my $line = $e->[2];
- if (($file eq $filename) &&
- ($line >= $firstline) &&
- ($line <= $lastline)) {
- # Assign all accumulated samples to this line
- AddEntry($samples1, $line, $running1);
- 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);
- 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 0;
- }
- my $l = 0;
- while (<FILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $l++;
- if ($l >= $firstline - 5 &&
- (($l <= $oldlastline + 5) || ($l <= $lastline))) {
- chop;
- my $text = $_;
- 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.
-# Returns undef if not found.
-sub SourceLine {
- my $file = shift;
- my $line = shift;
-
- # Look in cache
- if (!defined($main::source_cache{$file})) {
- if (100 < scalar keys(%main::source_cache)) {
- # Clear the cache when it gets too big
- $main::source_cache = ();
- }
-
- # Read all lines from the file
- if (!open(FILE, "<$file")) {
- print STDERR "$file: $!\n";
- $main::source_cache{$file} = []; # Cache the negative result
- return undef;
- }
- my $lines = [];
- push(@{$lines}, ""); # So we can use 1-based line numbers as indices
- while (<FILE>) {
- push(@{$lines}, $_);
- }
- close(FILE);
-
- # Save the lines in the cache
- $main::source_cache{$file} = $lines;
- }
-
- my $lines = $main::source_cache{$file};
- if (($line < 0) || ($line > $#{$lines})) {
- return undef;
- } else {
- return $lines->[$line];
- }
-}
-
-# Print disassembly for one routine with interspersed source if available
-sub PrintDisassembledFunction {
- my $prog = shift;
- my $offset = shift;
- my $routine = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $start_addr = shift;
- my $end_addr = shift;
- my $total = shift;
-
- # Disassemble all instructions
- my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);
-
- # Make array of counts per instruction
- my @flat_count = ();
- my @cum_count = ();
- my $flat_total = 0;
- my $cum_total = 0;
- foreach my $e (@instructions) {
- # Add up counts for all address that fall inside this instruction
- my $c1 = 0;
- my $c2 = 0;
- for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {
- $c1 += GetEntry($flat, $a);
- $c2 += GetEntry($cumulative, $a);
- }
- push(@flat_count, $c1);
- push(@cum_count, $c2);
- $flat_total += $c1;
- $cum_total += $c2;
- }
-
- # Print header with total counts
- printf("ROUTINE ====================== %s\n" .
- "%6s %6s %s (flat, cumulative) %.1f%% of total\n",
- ShortFunctionName($routine),
- Unparse($flat_total),
- Unparse($cum_total),
- Units(),
- ($cum_total * 100.0) / $total);
-
- # Process instructions in order
- my $current_file = "";
- for (my $i = 0; $i <= $#instructions; ) {
- my $e = $instructions[$i];
-
- # Print the new file name whenever we switch files
- if ($e->[1] ne $current_file) {
- $current_file = $e->[1];
- my $fname = $current_file;
- $fname =~ s|^\./||; # Trim leading "./"
-
- # Shorten long file names
- if (length($fname) >= 58) {
- $fname = "..." . substr($fname, -55);
- }
- printf("-------------------- %s\n", $fname);
- }
-
- # TODO: Compute range of lines to print together to deal with
- # small reorderings.
- my $first_line = $e->[2];
- my $last_line = $first_line;
- my %flat_sum = ();
- my %cum_sum = ();
- for (my $l = $first_line; $l <= $last_line; $l++) {
- $flat_sum{$l} = 0;
- $cum_sum{$l} = 0;
- }
-
- # Find run of instructions for this range of source lines
- my $first_inst = $i;
- while (($i <= $#instructions) &&
- ($instructions[$i]->[2] >= $first_line) &&
- ($instructions[$i]->[2] <= $last_line)) {
- $e = $instructions[$i];
- $flat_sum{$e->[2]} += $flat_count[$i];
- $cum_sum{$e->[2]} += $cum_count[$i];
- $i++;
- }
- my $last_inst = $i - 1;
-
- # Print source lines
- for (my $l = $first_line; $l <= $last_line; $l++) {
- my $line = SourceLine($current_file, $l);
- if (!defined($line)) {
- $line = "?\n";
- next;
- } else {
- $line =~ s/^\s+//;
- }
- printf("%6s %6s %5d: %s",
- UnparseAlt($flat_sum{$l}),
- UnparseAlt($cum_sum{$l}),
- $l,
- $line);
- }
-
- # Print disassembly
- for (my $x = $first_inst; $x <= $last_inst; $x++) {
- my $e = $instructions[$x];
- printf("%6s %6s %8s: %6s\n",
- UnparseAlt($flat_count[$x]),
- UnparseAlt($cum_count[$x]),
- UnparseAddress($offset, $e->[0]),
- CleanDisassembly($e->[3]));
- }
- }
-}
-
-# Print DOT graph
-sub PrintDot {
- my $prog = shift;
- my $symbols = shift;
- my $raw = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $overall_total = shift;
-
- # Get total
- my $local_total = TotalProfile($flat);
- my $nodelimit = int($main::opt_nodefraction * $local_total);
- my $edgelimit = int($main::opt_edgefraction * $local_total);
- my $nodecount = $main::opt_nodecount;
-
- # Find nodes to include
- my @list = (sort { abs(GetEntry($cumulative, $b)) <=>
- abs(GetEntry($cumulative, $a))
- || $a cmp $b }
- keys(%{$cumulative}));
- my $last = $nodecount - 1;
- if ($last > $#list) {
- $last = $#list;
- }
- while (($last >= 0) &&
- (abs(GetEntry($cumulative, $list[$last])) <= $nodelimit)) {
- $last--;
- }
- if ($last < 0) {
- print STDERR "No nodes to print\n";
- return 0;
- }
-
- if ($nodelimit > 0 || $edgelimit > 0) {
- printf STDERR ("Dropping nodes with <= %s %s; edges with <= %s abs(%s)\n",
- Unparse($nodelimit), Units(),
- Unparse($edgelimit), Units());
- }
-
- # Open DOT output file
- my $output;
- my $escaped_dot = ShellEscape(@DOT);
- my $escaped_ps2pdf = ShellEscape(@PS2PDF);
- if ($main::opt_gv) {
- my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "ps"));
- $output = "| $escaped_dot -Tps2 >$escaped_outfile";
- } elsif ($main::opt_evince) {
- my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "pdf"));
- $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - $escaped_outfile";
- } elsif ($main::opt_ps) {
- $output = "| $escaped_dot -Tps2";
- } elsif ($main::opt_pdf) {
- $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - -";
- } elsif ($main::opt_web || $main::opt_svg) {
- # We need to post-process the SVG, so write to a temporary file always.
- my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "svg"));
- $output = "| $escaped_dot -Tsvg >$escaped_outfile";
- } elsif ($main::opt_gif) {
- $output = "| $escaped_dot -Tgif";
- } else {
- $output = ">&STDOUT";
- }
- open(DOT, $output) || error("$output: $!\n");
-
- # Title
- printf DOT ("digraph \"%s; %s %s\" {\n",
- $prog,
- Unparse($overall_total),
- Units());
- if ($main::opt_pdf) {
- # The output is more printable if we set the page size for dot.
- printf DOT ("size=\"8,11\"\n");
- }
- printf DOT ("node [width=0.375,height=0.25];\n");
-
- # Print legend
- printf DOT ("Legend [shape=box,fontsize=24,shape=plaintext," .
- "label=\"%s\\l%s\\l%s\\l%s\\l%s\\l\"];\n",
- $prog,
- sprintf("Total %s: %s", Units(), Unparse($overall_total)),
- sprintf("Focusing on: %s", Unparse($local_total)),
- sprintf("Dropped nodes with <= %s abs(%s)",
- Unparse($nodelimit), Units()),
- sprintf("Dropped edges with <= %s %s",
- Unparse($edgelimit), Units())
- );
-
- # Print nodes
- my %node = ();
- my $nextnode = 1;
- foreach my $a (@list[0..$last]) {
- # Pick font size
- my $f = GetEntry($flat, $a);
- my $c = GetEntry($cumulative, $a);
-
- my $fs = 8;
- if ($local_total > 0) {
- $fs = 8 + (50.0 * sqrt(abs($f * 1.0 / $local_total)));
- }
-
- $node{$a} = $nextnode++;
- my $sym = $a;
- $sym =~ s/\s+/\\n/g;
- $sym =~ s/::/\\n/g;
-
- # Extra cumulative info to print for non-leaves
- my $extra = "";
- if ($f != $c) {
- $extra = sprintf("\\rof %s (%s)",
- Unparse($c),
- Percent($c, $local_total));
- }
- my $style = "";
- if ($main::opt_heapcheck) {
- if ($f > 0) {
- # make leak-causing nodes more visible (add a background)
- $style = ",style=filled,fillcolor=gray"
- } elsif ($f < 0) {
- # make anti-leak-causing nodes (which almost never occur)
- # stand out as well (triple border)
- $style = ",peripheries=3"
- }
- }
-
- printf DOT ("N%d [label=\"%s\\n%s (%s)%s\\r" .
- "\",shape=box,fontsize=%.1f%s];\n",
- $node{$a},
- $sym,
- Unparse($f),
- Percent($f, $local_total),
- $extra,
- $fs,
- $style,
- );
- }
-
- # Get edges and counts per edge
- my %edge = ();
- my $n;
- my $fullname_to_shortname_map = {};
- FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);
- foreach my $k (keys(%{$raw})) {
- # TODO: omit low %age edges
- $n = $raw->{$k};
- my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);
- for (my $i = 1; $i <= $#translated; $i++) {
- my $src = $translated[$i];
- my $dst = $translated[$i-1];
- #next if ($src eq $dst); # Avoid self-edges?
- if (exists($node{$src}) && exists($node{$dst})) {
- my $edge_label = "$src\001$dst";
- if (!exists($edge{$edge_label})) {
- $edge{$edge_label} = 0;
- }
- $edge{$edge_label} += $n;
- }
- }
- }
-
- # Print edges (process in order of decreasing counts)
- my %indegree = (); # Number of incoming edges added per node so far
- my %outdegree = (); # Number of outgoing edges added per node so far
- foreach my $e (sort { $edge{$b} <=> $edge{$a} } keys(%edge)) {
- my @x = split(/\001/, $e);
- $n = $edge{$e};
-
- # Initialize degree of kept incoming and outgoing edges if necessary
- my $src = $x[0];
- my $dst = $x[1];
- if (!exists($outdegree{$src})) { $outdegree{$src} = 0; }
- if (!exists($indegree{$dst})) { $indegree{$dst} = 0; }
-
- my $keep;
- if ($indegree{$dst} == 0) {
- # Keep edge if needed for reachability
- $keep = 1;
- } elsif (abs($n) <= $edgelimit) {
- # Drop if we are below --edgefraction
- $keep = 0;
- } elsif ($outdegree{$src} >= $main::opt_maxdegree ||
- $indegree{$dst} >= $main::opt_maxdegree) {
- # Keep limited number of in/out edges per node
- $keep = 0;
- } else {
- $keep = 1;
- }
-
- if ($keep) {
- $outdegree{$src}++;
- $indegree{$dst}++;
-
- # Compute line width based on edge count
- my $fraction = abs($local_total ? (3 * ($n / $local_total)) : 0);
- if ($fraction > 1) { $fraction = 1; }
- my $w = $fraction * 2;
- if ($w < 1 && ($main::opt_web || $main::opt_svg)) {
- # SVG output treats line widths < 1 poorly.
- $w = 1;
- }
-
- # Dot sometimes segfaults if given edge weights that are too large, so
- # we cap the weights at a large value
- my $edgeweight = abs($n) ** 0.7;
- if ($edgeweight > 100000) { $edgeweight = 100000; }
- $edgeweight = int($edgeweight);
-
- my $style = sprintf("setlinewidth(%f)", $w);
- if ($x[1] =~ m/\(inline\)/) {
- $style .= ",dashed";
- }
-
- # Use a slightly squashed function of the edge count as the weight
- printf DOT ("N%s -> N%s [label=%s, weight=%d, style=\"%s\"];\n",
- $node{$x[0]},
- $node{$x[1]},
- Unparse($n),
- $edgeweight,
- $style);
- }
- }
-
- print DOT ("}\n");
- close(DOT);
-
- if ($main::opt_web || $main::opt_svg) {
- # Rewrite SVG to be more usable inside web browser.
- RewriteSvg(TempName($main::next_tmpfile, "svg"));
- }
-
- return 1;
-}
-
-sub RewriteSvg {
- my $svgfile = shift;
-
- open(SVG, $svgfile) || die "open temp svg: $!";
- my @svg = <SVG>;
- close(SVG);
- unlink $svgfile;
- my $svg = join('', @svg);
-
- # Dot's SVG output is
- #
- # <svg width="___" height="___"
- # viewBox="___" xmlns=...>
- # <g id="graph0" transform="...">
- # ...
- # </g>
- # </svg>
- #
- # Change it to
- #
- # <svg width="100%" height="100%"
- # xmlns=...>
- # $svg_javascript
- # <g id="viewport" transform="translate(0,0)">
- # <g id="graph0" transform="...">
- # ...
- # </g>
- # </g>
- # </svg>
-
- # Fix width, height; drop viewBox.
- $svg =~ s/(?s)<svg width="[^"]+" height="[^"]+"(.*?)viewBox="[^"]+"/<svg width="100%" height="100%"$1/;
-
- # Insert script, viewport <g> above first <g>
- my $svg_javascript = SvgJavascript();
- my $viewport = "<g id=\"viewport\" transform=\"translate(0,0)\">\n";
- $svg =~ s/<g id="graph\d"/$svg_javascript$viewport$&/;
-
- # Insert final </g> above </svg>.
- $svg =~ s/(.*)(<\/svg>)/$1<\/g>$2/;
- $svg =~ s/<g id="graph\d"(.*?)/<g id="viewport"$1/;
-
- if ($main::opt_svg) {
- # --svg: write to standard output.
- print $svg;
- } else {
- # Write back to temporary file.
- open(SVG, ">$svgfile") || die "open $svgfile: $!";
- print SVG $svg;
- close(SVG);
- }
-}
-
-sub SvgJavascript {
- return <<'EOF';
-<script type="text/ecmascript"><![CDATA[
-// SVGPan
-// http://www.cyberz.org/blog/2009/12/08/svgpan-a-javascript-svg-panzoomdrag-library/
-// Local modification: if(true || ...) below to force panning, never moving.
-
-/**
- * SVGPan library 1.2
- * ====================
- *
- * Given an unique existing element with id "viewport", including the
- * the library into any SVG adds the following capabilities:
- *
- * - Mouse panning
- * - Mouse zooming (using the wheel)
- * - Object dargging
- *
- * Known issues:
- *
- * - Zooming (while panning) on Safari has still some issues
- *
- * Releases:
- *
- * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
- * Fixed a bug with browser mouse handler interaction
- *
- * 1.1, Wed Feb 3 17:39:33 GMT 2010, Zeng Xiaohui
- * Updated the zoom code to support the mouse wheel on Safari/Chrome
- *
- * 1.0, Andrea Leofreddi
- * First release
- *
- * This code is licensed under the following BSD license:
- *
- * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``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 Andrea Leofreddi 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.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of Andrea Leofreddi.
- */
-
-var root = document.documentElement;
-
-var state = 'none', stateTarget, stateOrigin, stateTf;
-
-setupHandlers(root);
-
-/**
- * Register handlers
- */
-function setupHandlers(root){
- setAttributes(root, {
- "onmouseup" : "add(evt)",
- "onmousedown" : "handleMouseDown(evt)",
- "onmousemove" : "handleMouseMove(evt)",
- "onmouseup" : "handleMouseUp(evt)",
- //"onmouseout" : "handleMouseUp(evt)", // Decomment this to stop the pan functionality when dragging out of the SVG element
- });
-
- if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)
- window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari
- else
- window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others
-
- var g = svgDoc.getElementById("svg");
- g.width = "100%";
- g.height = "100%";
-}
-
-/**
- * Instance an SVGPoint object with given event coordinates.
- */
-function getEventPoint(evt) {
- var p = root.createSVGPoint();
-
- p.x = evt.clientX;
- p.y = evt.clientY;
-
- return p;
-}
-
-/**
- * Sets the current transform matrix of an element.
- */
-function setCTM(element, matrix) {
- var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")";
-
- element.setAttribute("transform", s);
-}
-
-/**
- * Dumps a matrix to a string (useful for debug).
- */
-function dumpMatrix(matrix) {
- var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n " + matrix.b + ", " + matrix.d + ", " + matrix.f + "\n 0, 0, 1 ]";
-
- return s;
-}
-
-/**
- * Sets attributes of an element.
- */
-function setAttributes(element, attributes){
- for (i in attributes)
- element.setAttributeNS(null, i, attributes[i]);
-}
-
-/**
- * Handle mouse move event.
- */
-function handleMouseWheel(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- var delta;
-
- if(evt.wheelDelta)
- delta = evt.wheelDelta / 3600; // Chrome/Safari
- else
- delta = evt.detail / -90; // Mozilla
-
- var z = 1 + delta; // Zoom factor: 0.9/1.1
-
- var g = svgDoc.getElementById("viewport");
-
- var p = getEventPoint(evt);
-
- p = p.matrixTransform(g.getCTM().inverse());
-
- // Compute new scale matrix in current mouse position
- var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);
-
- setCTM(g, g.getCTM().multiply(k));
-
- stateTf = stateTf.multiply(k.inverse());
-}
-
-/**
- * Handle mouse move event.
- */
-function handleMouseMove(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- var g = svgDoc.getElementById("viewport");
-
- if(state == 'pan') {
- // Pan mode
- var p = getEventPoint(evt).matrixTransform(stateTf);
-
- setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));
- } else if(state == 'move') {
- // Move mode
- var p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());
-
- setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));
-
- stateOrigin = p;
- }
-}
-
-/**
- * Handle click event.
- */
-function handleMouseDown(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- var g = svgDoc.getElementById("viewport");
-
- if(true || evt.target.tagName == "svg") {
- // Pan mode
- state = 'pan';
-
- stateTf = g.getCTM().inverse();
-
- stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
- } else {
- // Move mode
- state = 'move';
-
- stateTarget = evt.target;
-
- stateTf = g.getCTM().inverse();
-
- stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
- }
-}
-
-/**
- * Handle mouse button release event.
- */
-function handleMouseUp(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- if(state == 'pan' || state == 'move') {
- // Quit pan mode
- state = '';
- }
-}
-
-]]></script>
-EOF
-}
-
-# Provides a map from fullname to shortname for cases where the
-# shortname is ambiguous. The symlist has both the fullname and
-# shortname for all symbols, which is usually fine, but sometimes --
-# such as overloaded functions -- two different fullnames can map to
-# the same shortname. In that case, we use the address of the
-# function to disambiguate the two. This function fills in a map that
-# maps fullnames to modified shortnames in such cases. If a fullname
-# is not present in the map, the 'normal' shortname provided by the
-# symlist is the appropriate one to use.
-sub FillFullnameToShortnameMap {
- my $symbols = shift;
- my $fullname_to_shortname_map = shift;
- my $shortnames_seen_once = {};
- my $shortnames_seen_more_than_once = {};
-
- foreach my $symlist (values(%{$symbols})) {
- # TODO(csilvers): deal with inlined symbols too.
- my $shortname = $symlist->[0];
- my $fullname = $symlist->[2];
- if ($fullname !~ /<[0-9a-fA-F]+>$/) { # fullname doesn't end in an address
- next; # the only collisions we care about are when addresses differ
- }
- if (defined($shortnames_seen_once->{$shortname}) &&
- $shortnames_seen_once->{$shortname} ne $fullname) {
- $shortnames_seen_more_than_once->{$shortname} = 1;
- } else {
- $shortnames_seen_once->{$shortname} = $fullname;
- }
- }
-
- foreach my $symlist (values(%{$symbols})) {
- my $shortname = $symlist->[0];
- my $fullname = $symlist->[2];
- # TODO(csilvers): take in a list of addresses we care about, and only
- # store in the map if $symlist->[1] is in that list. Saves space.
- next if defined($fullname_to_shortname_map->{$fullname});
- if (defined($shortnames_seen_more_than_once->{$shortname})) {
- if ($fullname =~ /<0*([^>]*)>$/) { # fullname has address at end of it
- $fullname_to_shortname_map->{$fullname} = "$shortname\@$1";
- }
- }
- }
-}
-
-# Return a small number that identifies the argument.
-# Multiple calls with the same argument will return the same number.
-# Calls with different arguments will return different numbers.
-sub ShortIdFor {
- my $key = shift;
- my $id = $main::uniqueid{$key};
- if (!defined($id)) {
- $id = keys(%main::uniqueid) + 1;
- $main::uniqueid{$key} = $id;
- }
- return $id;
-}
-
-# Translate a stack of addresses into a stack of symbols
-sub TranslateStack {
- my $symbols = shift;
- my $fullname_to_shortname_map = shift;
- my $k = shift;
-
- my @addrs = split(/\n/, $k);
- my @result = ();
- for (my $i = 0; $i <= $#addrs; $i++) {
- my $a = $addrs[$i];
-
- # Skip large addresses since they sometimes show up as fake entries on RH9
- if (length($a) > 8 && $a gt "7fffffffffffffff") {
- next;
- }
-
- if ($main::opt_disasm || $main::opt_list) {
- # We want just the address for the key
- push(@result, $a);
- next;
- }
-
- my $symlist = $symbols->{$a};
- if (!defined($symlist)) {
- $symlist = [$a, "", $a];
- }
-
- # We can have a sequence of symbols for a particular entry
- # (more than one symbol in the case of inlining). Callers
- # come before callees in symlist, so walk backwards since
- # the translated stack should contain callees before callers.
- for (my $j = $#{$symlist}; $j >= 2; $j -= 3) {
- my $func = $symlist->[$j-2];
- my $fileline = $symlist->[$j-1];
- my $fullfunc = $symlist->[$j];
- if (defined($fullname_to_shortname_map->{$fullfunc})) {
- $func = $fullname_to_shortname_map->{$fullfunc};
- }
- if ($j > 2) {
- $func = "$func (inline)";
- }
-
- # Do not merge nodes corresponding to Callback::Run since that
- # causes confusing cycles in dot display. Instead, we synthesize
- # a unique name for this frame per caller.
- if ($func =~ m/Callback.*::Run$/) {
- my $caller = ($i > 0) ? $addrs[$i-1] : 0;
- $func = "Run#" . ShortIdFor($caller);
- }
-
- if ($main::opt_addresses) {
- push(@result, "$a $func $fileline");
- } elsif ($main::opt_lines) {
- if ($func eq '??' && $fileline eq '??:0') {
- push(@result, "$a");
- } elsif (!$main::opt_show_addresses) {
- push(@result, "$func $fileline");
- } else {
- push(@result, "$func $fileline ($a)");
- }
- } elsif ($main::opt_functions) {
- if ($func eq '??') {
- push(@result, "$a");
- } elsif (!$main::opt_show_addresses) {
- push(@result, $func);
- } else {
- push(@result, "$func ($a)");
- }
- } elsif ($main::opt_files) {
- if ($fileline eq '??:0' || $fileline eq '') {
- push(@result, "$a");
- } else {
- my $f = $fileline;
- $f =~ s/:\d+$//;
- push(@result, $f);
- }
- } else {
- push(@result, $a);
- last; # Do not print inlined info
- }
- }
- }
-
- # print join(",", @addrs), " => ", join(",", @result), "\n";
- return @result;
-}
-
-# Generate percent string for a number and a total
-sub Percent {
- my $num = shift;
- my $tot = shift;
- if ($tot != 0) {
- return sprintf("%.1f%%", $num * 100.0 / $tot);
- } else {
- return ($num == 0) ? "nan" : (($num > 0) ? "+inf" : "-inf");
- }
-}
-
-# Generate pretty-printed form of number
-sub Unparse {
- my $num = shift;
- if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {
- if ($main::opt_inuse_objects || $main::opt_alloc_objects) {
- return sprintf("%d", $num);
- } else {
- if ($main::opt_show_bytes) {
- return sprintf("%d", $num);
- } else {
- return sprintf("%.1f", $num / 1048576.0);
- }
- }
- } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {
- return sprintf("%.3f", $num / 1e9); # Convert nanoseconds to seconds
- } else {
- return sprintf("%d", $num);
- }
-}
-
-# Alternate pretty-printed form: 0 maps to "."
-sub UnparseAlt {
- my $num = shift;
- if ($num == 0) {
- return ".";
- } else {
- return Unparse($num);
- }
-}
-
-# 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') {
- if ($main::opt_inuse_objects || $main::opt_alloc_objects) {
- return "objects";
- } else {
- if ($main::opt_show_bytes) {
- return "B";
- } else {
- return "MB";
- }
- }
- } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {
- return "seconds";
- } else {
- return "samples";
- }
-}
-
-##### Profile manipulation code #####
-
-# Generate flattened profile:
-# If count is charged to stack [a,b,c,d], in generated profile,
-# it will be charged to [a]
-sub FlatProfile {
- my $profile = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- if ($#addrs >= 0) {
- AddEntry($result, $addrs[0], $count);
- }
- }
- return $result;
-}
-
-# Generate cumulative profile:
-# If count is charged to stack [a,b,c,d], in generated profile,
-# it will be charged to [a], [b], [c], [d]
-sub CumulativeProfile {
- my $profile = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- foreach my $a (@addrs) {
- AddEntry($result, $a, $count);
- }
- }
- return $result;
-}
-
-# If the second-youngest PC on the stack is always the same, returns
-# that pc. Otherwise, returns undef.
-sub IsSecondPcAlwaysTheSame {
- my $profile = shift;
-
- my $second_pc = undef;
- foreach my $k (keys(%{$profile})) {
- my @addrs = split(/\n/, $k);
- if ($#addrs < 1) {
- return undef;
- }
- if (not defined $second_pc) {
- $second_pc = $addrs[1];
- } else {
- if ($second_pc ne $addrs[1]) {
- return undef;
- }
- }
- }
- return $second_pc;
-}
-
-sub ExtractSymbolLocationInlineStack {
- my $symbols = shift;
- my $address = shift;
- my $stack = shift;
- # 'addr2line' outputs "??:0" for unknown locations; we do the
- # same to be consistent.
- if (exists $symbols->{$address}) {
- my @localinlinestack = @{$symbols->{$address}};
- for (my $i = $#localinlinestack; $i > 0; $i-=3) {
- my $file = $localinlinestack[$i-1];
- my $fn = $localinlinestack[$i-2];
- if ($file eq "?" || $file eq ":0") {
- $file = "??:0";
- }
- my $suffix = "[inline]";
- if ($i == 2) {
- $suffix = "";
- }
- push (@$stack, $file.":".$fn.$suffix);
- }
- }
- else {
- push (@$stack, "??:0:unknown");
- }
-}
-
-sub ExtractSymbolNameInlineStack {
- my $symbols = shift;
- my $address = shift;
-
- my @stack = ();
-
- if (exists $symbols->{$address}) {
- my @localinlinestack = @{$symbols->{$address}};
- for (my $i = $#localinlinestack; $i > 0; $i-=3) {
- my $file = $localinlinestack[$i-1];
- my $fn = $localinlinestack[$i-0];
-
- if ($file eq "?" || $file eq ":0") {
- $file = "??:0";
- }
- if ($fn eq '??') {
- # If we can't get the symbol name, at least use the file information.
- $fn = $file;
- }
- my $suffix = "[inline]";
- if ($i == 2) {
- $suffix = "";
- }
- push (@stack, $fn.$suffix);
- }
- }
- else {
- # If we can't get a symbol name, at least fill in the address.
- push (@stack, $address);
- }
-
- return @stack;
-}
-
-sub ExtractSymbolLocation {
- my $symbols = shift;
- my $address = shift;
- # 'addr2line' outputs "??:0" for unknown locations; we do the
- # same to be consistent.
- my $location = "??:0:unknown";
- if (exists $symbols->{$address}) {
- my $file = $symbols->{$address}->[1];
- if ($file eq "?" || $file eq ":0") {
- $file = "??:0"
- }
- $location = $file . ":" . $symbols->{$address}->[0];
- }
- return $location;
-}
-
-# Extracts a graph of calls.
-sub ExtractCalls {
- my $symbols = shift;
- my $profile = shift;
- my $calls = {};
- while( my ($stack_trace, $count) = each %$profile ) {
- my @address = split(/\n/, $stack_trace);
- my @stack = ();
- ExtractSymbolLocationInlineStack($symbols, $address[0], \@stack);
- for (my $i = 1; $i <= $#address; $i++) {
- ExtractSymbolLocationInlineStack($symbols, $address[$i], \@stack);
- }
- AddEntry($calls, $stack[0], $count);
- for (my $i = 1; $i < $#address; $i++) {
- AddEntry($calls, "$stack[$i] -> $stack[$i-1]", $count);
- }
- }
- return $calls;
-}
-
-sub PrintStacksForText {
- my $symbols = shift;
- my $profile = shift;
-
- while (my ($stack_trace, $count) = each %$profile) {
- my @address = split(/\n/, $stack_trace);
- for (my $i = 0; $i <= $#address; $i++) {
- $address[$i] = sprintf("(%s) %s", $address[$i], ExtractSymbolLocation($symbols, $address[$i]));
- }
- printf("%-8d %s\n\n", $count, join("\n ", @address));
- }
-}
-
-sub PrintCollapsedStacks {
- my $symbols = shift;
- my $profile = shift;
-
- while (my ($stack_trace, $count) = each %$profile) {
- my @address = split(/\n/, $stack_trace);
- my @names = reverse ( map { ExtractSymbolNameInlineStack($symbols, $_) } @address );
- printf("%s %d\n", join(";", @names), $count);
- }
-}
-
-sub RemoveUninterestingFrames {
- my $symbols = shift;
- my $profile = shift;
-
- # List of function names to skip
- my %skip = ();
- my $skip_regexp = 'NOMATCH';
- if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {
- foreach my $name ('calloc',
- 'cfree',
- 'malloc',
- 'free',
- 'memalign',
- 'posix_memalign',
- 'pvalloc',
- 'valloc',
- 'realloc',
- 'tc_calloc',
- 'tc_cfree',
- 'tc_malloc',
- 'tc_free',
- 'tc_memalign',
- 'tc_posix_memalign',
- 'tc_pvalloc',
- 'tc_valloc',
- 'tc_realloc',
- 'tc_new',
- 'tc_delete',
- 'tc_newarray',
- 'tc_deletearray',
- 'tc_new_nothrow',
- 'tc_newarray_nothrow',
- 'do_malloc',
- '::do_malloc', # new name -- got moved to an unnamed ns
- '::do_malloc_or_cpp_alloc',
- 'DoSampledAllocation',
- 'simple_alloc::allocate',
- '__malloc_alloc_template::allocate',
- '__builtin_delete',
- '__builtin_new',
- '__builtin_vec_delete',
- '__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',
- '__start_malloc_hook',
- '__stop_malloc_hook') {
- $skip{$name} = 1;
- $skip{"_" . $name} = 1; # Mach (OS X) adds a _ prefix to everything
- }
- # TODO: Remove TCMalloc once everything has been
- # moved into the tcmalloc:: namespace and we have flushed
- # old code out of the system.
- $skip_regexp = "TCMalloc|^tcmalloc::";
- } elsif ($main::profile_type eq 'contention') {
- foreach my $vname ('base::RecordLockProfileData',
- 'base::SubmitMutexProfileData',
- 'base::SubmitSpinLockProfileData',
- 'Mutex::Unlock',
- 'Mutex::UnlockSlow',
- 'Mutex::ReaderUnlock',
- 'MutexLock::~MutexLock',
- 'SpinLock::Unlock',
- 'SpinLock::SlowUnlock',
- 'SpinLockHolder::~SpinLockHolder') {
- $skip{$vname} = 1;
- }
- } elsif ($main::profile_type eq 'cpu' && !$main::opt_no_auto_signal_frames) {
- # Drop signal handlers used for CPU profile collection
- # TODO(dpeng): this should not be necessary; it's taken
- # care of by the general 2nd-pc mechanism below.
- foreach my $name ('ProfileData::Add', # historical
- 'ProfileData::prof_handler', # historical
- 'CpuProfiler::prof_handler',
- '__FRAME_END__',
- '__pthread_sighandler',
- '__restore') {
- $skip{$name} = 1;
- }
- } else {
- # Nothing skipped for unknown types
- }
-
- if ($main::profile_type eq 'cpu') {
- # If all the second-youngest program counters are the same,
- # this STRONGLY suggests that it is an artifact of measurement,
- # i.e., stack frames pushed by the CPU profiler signal handler.
- # Hence, we delete them.
- # (The topmost PC is read from the signal structure, not from
- # the stack, so it does not get involved.)
- while (my $second_pc = IsSecondPcAlwaysTheSame($profile)) {
- my $result = {};
- my $func = '';
- if (exists($symbols->{$second_pc})) {
- $second_pc = $symbols->{$second_pc}->[0];
- }
- if ($main::opt_no_auto_signal_frames) {
- print STDERR "All second stack frames are same: `$second_pc'.\nMight be stack trace capturing bug.\n";
- last;
- }
- print STDERR "Removing $second_pc from all stack traces.\n";
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- my $topaddr = POSIX::strtoul($addrs[0], 16);
- splice @addrs, 1, 1;
- if ($#addrs > 1) {
- my $subtopaddr = POSIX::strtoul($addrs[1], 16);
- if ($subtopaddr + 1 == $topaddr) {
- splice @addrs, 1, 1;
- }
- }
- my $reduced_path = join("\n", @addrs);
- AddEntry($result, $reduced_path, $count);
- }
- $profile = $result;
- }
- }
-
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- my @path = ();
- foreach my $a (@addrs) {
- if (exists($symbols->{$a})) {
- my $func = $symbols->{$a}->[0];
- if ($skip{$func} || ($func =~ m/$skip_regexp/)) {
- next;
- }
- }
- push(@path, $a);
- }
- my $reduced_path = join("\n", @path);
- AddEntry($result, $reduced_path, $count);
- }
- return $result;
-}
-
-# Reduce profile to granularity given by user
-sub ReduceProfile {
- my $symbols = shift;
- my $profile = shift;
- my $result = {};
- my $fullname_to_shortname_map = {};
- FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);
- my @path = ();
- my %seen = ();
- $seen{''} = 1; # So that empty keys are skipped
- foreach my $e (@translated) {
- # To avoid double-counting due to recursion, skip a stack-trace
- # entry if it has already been seen
- if (!$seen{$e}) {
- $seen{$e} = 1;
- push(@path, $e);
- }
- }
- my $reduced_path = join("\n", @path);
- AddEntry($result, $reduced_path, $count);
- }
- return $result;
-}
-
-# Does the specified symbol array match the regexp?
-sub SymbolMatches {
- my $sym = shift;
- my $re = shift;
- if (defined($sym)) {
- for (my $i = 0; $i < $#{$sym}; $i += 3) {
- if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-# Focus only on paths involving specified regexps
-sub FocusProfile {
- my $symbols = shift;
- my $profile = shift;
- my $focus = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- foreach my $a (@addrs) {
- # Reply if it matches either the address/shortname/fileline
- if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) {
- AddEntry($result, $k, $count);
- last;
- }
- }
- }
- return $result;
-}
-
-# Focus only on paths not involving specified regexps
-sub IgnoreProfile {
- my $symbols = shift;
- my $profile = shift;
- my $ignore = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- my $matched = 0;
- foreach my $a (@addrs) {
- # Reply if it matches either the address/shortname/fileline
- if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) {
- $matched = 1;
- last;
- }
- }
- if (!$matched) {
- AddEntry($result, $k, $count);
- }
- }
- return $result;
-}
-
-# Get total count in profile
-sub TotalProfile {
- my $profile = shift;
- my $result = 0;
- foreach my $k (keys(%{$profile})) {
- $result += $profile->{$k};
- }
- return $result;
-}
-
-# Add A to B
-sub AddProfile {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- # add all keys in A
- foreach my $k (keys(%{$A})) {
- my $v = $A->{$k};
- AddEntry($R, $k, $v);
- }
- # add all keys in B
- foreach my $k (keys(%{$B})) {
- my $v = $B->{$k};
- AddEntry($R, $k, $v);
- }
- return $R;
-}
-
-# Merges symbol maps
-sub MergeSymbols {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- foreach my $k (keys(%{$A})) {
- $R->{$k} = $A->{$k};
- }
- if (defined($B)) {
- foreach my $k (keys(%{$B})) {
- $R->{$k} = $B->{$k};
- }
- }
- return $R;
-}
-
-
-# Add A to B
-sub AddPcs {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- # add all keys in A
- foreach my $k (keys(%{$A})) {
- $R->{$k} = 1
- }
- # add all keys in B
- foreach my $k (keys(%{$B})) {
- $R->{$k} = 1
- }
- return $R;
-}
-
-# Subtract B from A
-sub SubtractProfile {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- foreach my $k (keys(%{$A})) {
- my $v = $A->{$k} - GetEntry($B, $k);
- if ($v < 0 && $main::opt_drop_negative) {
- $v = 0;
- }
- AddEntry($R, $k, $v);
- }
- if (!$main::opt_drop_negative) {
- # Take care of when subtracted profile has more entries
- foreach my $k (keys(%{$B})) {
- if (!exists($A->{$k})) {
- AddEntry($R, $k, 0 - $B->{$k});
- }
- }
- }
- return $R;
-}
-
-# Get entry from profile; zero if not present
-sub GetEntry {
- my $profile = shift;
- my $k = shift;
- if (exists($profile->{$k})) {
- return $profile->{$k};
- } else {
- return 0;
- }
-}
-
-# Add entry to specified profile
-sub AddEntry {
- my $profile = shift;
- my $k = shift;
- my $n = shift;
- if (!exists($profile->{$k})) {
- $profile->{$k} = 0;
- }
- $profile->{$k} += $n;
-}
-
-# Add a stack of entries to specified profile, and add them to the $pcs
-# list.
-sub AddEntries {
- my $profile = shift;
- my $pcs = shift;
- my $stack = shift;
- my $count = shift;
- my @k = ();
-
- foreach my $e (split(/\s+/, $stack)) {
- my $pc = HexExtend($e);
- $pcs->{$pc} = 1;
- push @k, $pc;
- }
- AddEntry($profile, (join "\n", @k), $count);
-}
-
-##### Code to profile a server dynamically #####
-
-sub CheckSymbolPage {
- my $url = SymbolPageURL();
- my $command = ShellEscape(@URL_FETCHER, $url);
- open(SYMBOL, "$command |") or error($command);
- my $line = <SYMBOL>;
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- close(SYMBOL);
- unless (defined($line)) {
- error("$url doesn't exist\n");
- }
-
- if ($line =~ /^num_symbols:\s+(\d+)$/) {
- if ($1 == 0) {
- error("Stripped binary. No symbols available.\n");
- }
- } else {
- error("Failed to get the number of symbols from $url\n");
- }
-}
-
-sub IsProfileURL {
- my $profile_name = shift;
- if (-f $profile_name) {
- printf STDERR "Using local file $profile_name.\n";
- return 0;
- }
- return 1;
-}
-
-sub ParseProfileURL {
- my $profile_name = shift;
-
- if (!defined($profile_name) || $profile_name eq "") {
- return ();
- }
-
- # Split profile URL - matches all non-empty strings, so no test.
- $profile_name =~ m,^(https?://)?([^/]+)(.*?)(/|$PROFILES)?$,;
-
- my $proto = $1 || "http://";
- my $hostport = $2;
- my $prefix = $3;
- my $profile = $4 || "/";
-
- my $host = $hostport;
- $host =~ s/:.*//;
-
- my $baseurl = "$proto$hostport$prefix";
- return ($host, $baseurl, $profile);
-}
-
-# We fetch symbols from the first profile argument.
-sub SymbolPageURL {
- my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);
- return "$baseURL$SYMBOL_PAGE";
-}
-
-sub FetchProgramName() {
- my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);
- my $url = "$baseURL$PROGRAM_NAME_PAGE";
- my $command_line = ShellEscape(@URL_FETCHER, $url);
- open(CMDLINE, "$command_line |") or error($command_line);
- my $cmdline = <CMDLINE>;
- $cmdline =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- close(CMDLINE);
- error("Failed to get program name from $url\n") unless defined($cmdline);
- $cmdline =~ s/\x00.+//; # Remove argv[1] and latters.
- $cmdline =~ s!\n!!g; # Remove LFs.
- return $cmdline;
-}
-
-# Gee, curl's -L (--location) option isn't reliable at least
-# with its 7.12.3 version. Curl will forget to post data if
-# there is a redirection. This function is a workaround for
-# curl. Redirection happens on borg hosts.
-sub ResolveRedirectionForCurl {
- my $url = shift;
- my $command_line = ShellEscape(@URL_FETCHER, "--head", $url);
- open(CMDLINE, "$command_line |") or error($command_line);
- while (<CMDLINE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- if (/^Location: (.*)/) {
- $url = $1;
- }
- }
- close(CMDLINE);
- return $url;
-}
-
-# Add a timeout flat to URL_FETCHER. Returns a new list.
-sub AddFetchTimeout {
- my $timeout = shift;
- my @fetcher = @_;
- if (defined($timeout)) {
- if (join(" ", @fetcher) =~ m/\bcurl -s/) {
- push(@fetcher, "--max-time", sprintf("%d", $timeout));
- } elsif (join(" ", @fetcher) =~ m/\brpcget\b/) {
- push(@fetcher, sprintf("--deadline=%d", $timeout));
- }
- }
- return @fetcher;
-}
-
-# Reads a symbol map from the file handle name given as $1, returning
-# the resulting symbol map. Also processes variables relating to symbols.
-# Currently, the only variable processed is 'binary=<value>' which updates
-# $main::prog to have the correct program name.
-sub ReadSymbols {
- my $in = shift;
- my $map = {};
- while (<$in>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Removes all the leading zeroes from the symbols, see comment below.
- if (m/^0x0*([0-9a-f]+)\s+(.+)/) {
- $map->{$1} = $2;
- } elsif (m/^---/) {
- last;
- } elsif (m/^([a-z][^=]*)=(.*)$/ ) {
- my ($variable, $value) = ($1, $2);
- for ($variable, $value) {
- s/^\s+//;
- s/\s+$//;
- }
- if ($variable eq "binary") {
- if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) {
- printf STDERR ("Warning: Mismatched binary name '%s', using '%s'.\n",
- $main::prog, $value);
- }
- $main::prog = $value;
- } else {
- printf STDERR ("Ignoring unknown variable in symbols list: " .
- "'%s' = '%s'\n", $variable, $value);
- }
- }
- }
- return $map;
-}
-
-# Fetches and processes symbols to prepare them for use in the profile output
-# code. If the optional 'symbol_map' arg is not given, fetches symbols from
-# $SYMBOL_PAGE for all PC values found in profile. Otherwise, the raw symbols
-# are assumed to have already been fetched into 'symbol_map' and are simply
-# extracted and processed.
-sub FetchSymbols {
- my $pcset = shift;
- my $symbol_map = shift;
-
- my %seen = ();
- my @pcs = grep { !$seen{$_}++ } keys(%$pcset); # uniq
-
- if (!defined($symbol_map)) {
- my $post_data = join("+", sort((map {"0x" . "$_"} @pcs)));
-
- open(POSTFILE, ">$main::tmpfile_sym");
- print POSTFILE $post_data;
- close(POSTFILE);
-
- my $url = SymbolPageURL();
-
- my $command_line;
- if (join(" ", @URL_FETCHER) =~ m/\bcurl -s/) {
- $url = ResolveRedirectionForCurl($url);
- $command_line = ShellEscape(@URL_FETCHER, "-d", "\@$main::tmpfile_sym",
- $url);
- } else {
- $command_line = (ShellEscape(@URL_FETCHER, "--post", $url)
- . " < " . ShellEscape($main::tmpfile_sym));
- }
- # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols.
- my $escaped_cppfilt = ShellEscape($obj_tool_map{"c++filt"});
- open(SYMBOL, "$command_line | $escaped_cppfilt |") or error($command_line);
- $symbol_map = ReadSymbols(*SYMBOL{IO});
- close(SYMBOL);
- }
-
- my $symbols = {};
- foreach my $pc (@pcs) {
- my $fullname;
- # For 64 bits binaries, symbols are extracted with 8 leading zeroes.
- # Then /symbol reads the long symbols in as uint64, and outputs
- # the result with a "0x%08llx" format which get rid of the zeroes.
- # By removing all the leading zeroes in both $pc and the symbols from
- # /symbol, the symbols match and are retrievable from the map.
- my $shortpc = $pc;
- $shortpc =~ s/^0*//;
- # Each line may have a list of names, which includes the function
- # and also other functions it has inlined. They are separated (in
- # PrintSymbolizedProfile), by --, which is illegal in function names.
- my $fullnames;
- if (defined($symbol_map->{$shortpc})) {
- $fullnames = $symbol_map->{$shortpc};
- } else {
- $fullnames = "0x" . $pc; # Just use addresses
- }
- my $sym = [];
- $symbols->{$pc} = $sym;
- foreach my $fullname (split("--", $fullnames)) {
- my $name = ShortFunctionName($fullname);
- push(@{$sym}, $name, "?", $fullname);
- }
- }
- return $symbols;
-}
-
-sub BaseName {
- my $file_name = shift;
- $file_name =~ s!^.*/!!; # Remove directory name
- return $file_name;
-}
-
-sub MakeProfileBaseName {
- my ($binary_name, $profile_name) = @_;
- my ($host, $baseURL, $path) = ParseProfileURL($profile_name);
- my $binary_shortname = BaseName($binary_name);
- return sprintf("%s.%s.%s",
- $binary_shortname, $main::op_time, $host);
-}
-
-sub FetchDynamicProfile {
- my $binary_name = shift;
- my $profile_name = shift;
- my $fetch_name_only = shift;
- my $encourage_patience = shift;
-
- if (!IsProfileURL($profile_name)) {
- return $profile_name;
- } else {
- my ($host, $baseURL, $path) = ParseProfileURL($profile_name);
- if ($path eq "" || $path eq "/") {
- # Missing type specifier defaults to cpu-profile
- $path = $PROFILE_PAGE;
- }
-
- my $profile_file = MakeProfileBaseName($binary_name, $profile_name);
-
- my $url = "$baseURL$path";
- my $fetch_timeout = undef;
- if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE/) {
- if ($path =~ m/[?]/) {
- $url .= "&";
- } else {
- $url .= "?";
- }
- $url .= sprintf("seconds=%d", $main::opt_seconds);
- $fetch_timeout = $main::opt_seconds * 1.01 + 60;
- } else {
- # For non-CPU profiles, we add a type-extension to
- # the target profile file name.
- my $suffix = $path;
- $suffix =~ s,/,.,g;
- $profile_file .= $suffix;
- }
-
- my $profile_dir = $ENV{"PPROF_TMPDIR"} || ($ENV{HOME} . "/pprof");
- if (! -d $profile_dir) {
- mkdir($profile_dir)
- || die("Unable to create profile directory $profile_dir: $!\n");
- }
- my $tmp_profile = "$profile_dir/.tmp.$profile_file";
- my $real_profile = "$profile_dir/$profile_file";
-
- if ($fetch_name_only > 0) {
- return $real_profile;
- }
-
- my @fetcher = AddFetchTimeout($fetch_timeout, @URL_FETCHER);
- my $cmd = ShellEscape(@fetcher, $url) . " > " . ShellEscape($tmp_profile);
- if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE|$CENSUSPROFILE_PAGE/){
- print STDERR "Gathering CPU profile from $url for $main::opt_seconds seconds to\n ${real_profile}\n";
- if ($encourage_patience) {
- print STDERR "Be patient...\n";
- }
- } else {
- print STDERR "Fetching $path profile from $url to\n ${real_profile}\n";
- }
-
- (system($cmd) == 0) || error("Failed to get profile: $cmd: $!\n");
- (system("mv", $tmp_profile, $real_profile) == 0) || error("Unable to rename profile\n");
- print STDERR "Wrote profile to $real_profile\n";
- $main::collected_profile = $real_profile;
- return $main::collected_profile;
- }
-}
-
-# Collect profiles in parallel
-sub FetchDynamicProfiles {
- my $items = scalar(@main::pfile_args);
- my $levels = log($items) / log(2);
-
- if ($items == 1) {
- $main::profile_files[0] = FetchDynamicProfile($main::prog, $main::pfile_args[0], 0, 1);
- } else {
- # math rounding issues
- if ((2 ** $levels) < $items) {
- $levels++;
- }
- my $count = scalar(@main::pfile_args);
- for (my $i = 0; $i < $count; $i++) {
- $main::profile_files[$i] = FetchDynamicProfile($main::prog, $main::pfile_args[$i], 1, 0);
- }
- print STDERR "Fetching $count profiles, Be patient...\n";
- FetchDynamicProfilesRecurse($levels, 0, 0);
- $main::collected_profile = join(" \\\n ", @main::profile_files);
- }
-}
-
-# Recursively fork a process to get enough processes
-# collecting profiles
-sub FetchDynamicProfilesRecurse {
- my $maxlevel = shift;
- my $level = shift;
- my $position = shift;
-
- if (my $pid = fork()) {
- $position = 0 | ($position << 1);
- TryCollectProfile($maxlevel, $level, $position);
- wait;
- } else {
- $position = 1 | ($position << 1);
- TryCollectProfile($maxlevel, $level, $position);
- cleanup();
- exit(0);
- }
-}
-
-# Collect a single profile
-sub TryCollectProfile {
- my $maxlevel = shift;
- my $level = shift;
- my $position = shift;
-
- if ($level >= ($maxlevel - 1)) {
- if ($position < scalar(@main::pfile_args)) {
- FetchDynamicProfile($main::prog, $main::pfile_args[$position], 0, 0);
- }
- } else {
- FetchDynamicProfilesRecurse($maxlevel, $level+1, $position);
- }
-}
-
-##### Parsing code #####
-
-# Provide a small streaming-read module to handle very large
-# cpu-profile files. Stream in chunks along a sliding window.
-# Provides an interface to get one 'slot', correctly handling
-# endian-ness differences. A slot is one 32-bit or 64-bit word
-# (depending on the input profile). We tell endianness and bit-size
-# for the profile by looking at the first 8 bytes: in cpu profiles,
-# the second slot is always 3 (we'll accept anything that's not 0).
-BEGIN {
- package CpuProfileStream;
-
- sub new {
- my ($class, $file, $fname) = @_;
- my $self = { file => $file,
- base => 0,
- stride => 512 * 1024, # must be a multiple of bitsize/8
- slots => [],
- unpack_code => "", # N for big-endian, V for little
- perl_is_64bit => 1, # matters if profile is 64-bit
- };
- bless $self, $class;
- # Let unittests adjust the stride
- if ($main::opt_test_stride > 0) {
- $self->{stride} = $main::opt_test_stride;
- }
- # Read the first two slots to figure out bitsize and endianness.
- my $slots = $self->{slots};
- my $str;
- read($self->{file}, $str, 8);
- # Set the global $address_length based on what we see here.
- # 8 is 32-bit (8 hexadecimal chars); 16 is 64-bit (16 hexadecimal chars).
- $address_length = ($str eq (chr(0)x8)) ? 16 : 8;
- if ($address_length == 8) {
- if (substr($str, 6, 2) eq chr(0)x2) {
- $self->{unpack_code} = 'V'; # Little-endian.
- } elsif (substr($str, 4, 2) eq chr(0)x2) {
- $self->{unpack_code} = 'N'; # Big-endian
- } else {
- ::error("$fname: header size >= 2**16\n");
- }
- @$slots = unpack($self->{unpack_code} . "*", $str);
- } else {
- # If we're a 64-bit profile, check if we're a 64-bit-capable
- # perl. Otherwise, each slot will be represented as a float
- # instead of an int64, losing precision and making all the
- # 64-bit addresses wrong. We won't complain yet, but will
- # later if we ever see a value that doesn't fit in 32 bits.
- my $has_q = 0;
- eval { $has_q = pack("Q", "1") ? 1 : 1; };
- if (!$has_q) {
- $self->{perl_is_64bit} = 0;
- }
- read($self->{file}, $str, 8);
- if (substr($str, 4, 4) eq chr(0)x4) {
- # We'd love to use 'Q', but it's a) not universal, b) not endian-proof.
- $self->{unpack_code} = 'V'; # Little-endian.
- } elsif (substr($str, 0, 4) eq chr(0)x4) {
- $self->{unpack_code} = 'N'; # Big-endian
- } else {
- ::error("$fname: header size >= 2**32\n");
- }
- my @pair = unpack($self->{unpack_code} . "*", $str);
- # Since we know one of the pair is 0, it's fine to just add them.
- @$slots = (0, $pair[0] + $pair[1]);
- }
- return $self;
- }
-
- # Load more data when we access slots->get(X) which is not yet in memory.
- sub overflow {
- my ($self) = @_;
- my $slots = $self->{slots};
- $self->{base} += $#$slots + 1; # skip over data we're replacing
- my $str;
- read($self->{file}, $str, $self->{stride});
- if ($address_length == 8) { # the 32-bit case
- # This is the easy case: unpack provides 32-bit unpacking primitives.
- @$slots = unpack($self->{unpack_code} . "*", $str);
- } else {
- # We need to unpack 32 bits at a time and combine.
- my @b32_values = unpack($self->{unpack_code} . "*", $str);
- my @b64_values = ();
- for (my $i = 0; $i < $#b32_values; $i += 2) {
- # TODO(csilvers): if this is a 32-bit perl, the math below
- # could end up in a too-large int, which perl will promote
- # to a double, losing necessary precision. Deal with that.
- # Right now, we just die.
- my ($lo, $hi) = ($b32_values[$i], $b32_values[$i+1]);
- if ($self->{unpack_code} eq 'N') { # big-endian
- ($lo, $hi) = ($hi, $lo);
- }
- my $value = $lo + $hi * (2**32);
- if (!$self->{perl_is_64bit} && # check value is exactly represented
- (($value % (2**32)) != $lo || int($value / (2**32)) != $hi)) {
- ::error("Need a 64-bit perl to process this 64-bit profile.\n");
- }
- push(@b64_values, $value);
- }
- @$slots = @b64_values;
- }
- }
-
- # Access the i-th long in the file (logically), or -1 at EOF.
- sub get {
- my ($self, $idx) = @_;
- my $slots = $self->{slots};
- while ($#$slots >= 0) {
- if ($idx < $self->{base}) {
- # The only time we expect a reference to $slots[$i - something]
- # after referencing $slots[$i] is reading the very first header.
- # Since $stride > |header|, that shouldn't cause any lookback
- # errors. And everything after the header is sequential.
- print STDERR "Unexpected look-back reading CPU profile";
- return -1; # shrug, don't know what better to return
- } elsif ($idx > $self->{base} + $#$slots) {
- $self->overflow();
- } else {
- return $slots->[$idx - $self->{base}];
- }
- }
- # If we get here, $slots is [], which means we've reached EOF
- return -1; # unique since slots is supposed to hold unsigned numbers
- }
-}
-
-# Reads the top, 'header' section of a profile, and returns the last
-# line of the header, commonly called a 'header line'. The header
-# section of a profile consists of zero or more 'command' lines that
-# are instructions to pprof, which pprof executes when reading the
-# header. All 'command' lines start with a %. After the command
-# lines is the 'header line', which is a profile-specific line that
-# indicates what type of profile it is, and perhaps other global
-# information about the profile. For instance, here's a header line
-# for a heap profile:
-# heap profile: 53: 38236 [ 5525: 1284029] @ heapprofile
-# For historical reasons, the CPU profile does not contain a text-
-# readable header line. If the profile looks like a CPU profile,
-# this function returns "". If no header line could be found, this
-# function returns undef.
-#
-# The following commands are recognized:
-# %warn -- emit the rest of this line to stderr, prefixed by 'WARNING:'
-#
-# The input file should be in binmode.
-sub ReadProfileHeader {
- local *PROFILE = shift;
- my $firstchar = "";
- my $line = "";
- read(PROFILE, $firstchar, 1);
- seek(PROFILE, -1, 1); # unread the firstchar
- if ($firstchar !~ /[[:print:]]/) { # is not a text character
- return "";
- }
- while (defined($line = <PROFILE>)) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- if ($line =~ /^%warn\s+(.*)/) { # 'warn' command
- # Note this matches both '%warn blah\n' and '%warn\n'.
- print STDERR "WARNING: $1\n"; # print the rest of the line
- } elsif ($line =~ /^%/) {
- print STDERR "Ignoring unknown command from profile header: $line";
- } else {
- # End of commands, must be the header line.
- return $line;
- }
- }
- return undef; # got to EOF without seeing a header line
-}
-
-sub IsSymbolizedProfileFile {
- my $file_name = shift;
- if (!(-e $file_name) || !(-r $file_name)) {
- return 0;
- }
- # Check if the file contains a symbol-section marker.
- open(TFILE, "<$file_name");
- binmode TFILE;
- my $firstline = ReadProfileHeader(*TFILE);
- close(TFILE);
- if (!$firstline) {
- return 0;
- }
- $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $symbol_marker = $&;
- return $firstline =~ /^--- *$symbol_marker/;
-}
-
-# Parse profile generated by common/profiler.cc and return a reference
-# to a map:
-# $result->{version} Version number of profile file
-# $result->{period} Sampling period (in microseconds)
-# $result->{profile} Profile object
-# $result->{map} Memory map info from profile
-# $result->{pcs} Hash of all PC values seen, key is hex address
-sub ReadProfile {
- my $prog = shift;
- my $fname = shift;
- my $result; # return value
-
- $CONTENTION_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $contention_marker = $&;
- $GROWTH_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $growth_marker = $&;
- $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $symbol_marker = $&;
- $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $profile_marker = $&;
-
- # Look at first line to see if it is a heap or a CPU profile.
- # CPU profile may start with no header at all, and just binary data
- # (starting with \0\0\0\0) -- in that case, don't try to read the
- # whole firstline, since it may be gigabytes(!) of data.
- open(PROFILE, "<$fname") || error("$fname: $!\n");
- binmode PROFILE; # New perls do UTF-8 processing
- my $header = ReadProfileHeader(*PROFILE);
- if (!defined($header)) { # means "at EOF"
- error("Profile is empty.\n");
- }
-
- my $symbols;
- if ($header =~ m/^--- *$symbol_marker/o) {
- # Verify that the user asked for a symbolized profile
- if (!$main::use_symbolized_profile) {
- # we have both a binary and symbolized profiles, abort
- error("FATAL ERROR: Symbolized profile\n $fname\ncannot be used with " .
- "a binary arg. Try again without passing\n $prog\n");
- }
- # Read the symbol section of the symbolized profile file.
- $symbols = ReadSymbols(*PROFILE{IO});
- # Read the next line to get the header for the remaining profile.
- $header = ReadProfileHeader(*PROFILE) || "";
- }
-
- $main::profile_type = '';
- if ($header =~ m/^heap profile:.*$growth_marker/o) {
- $main::profile_type = 'growth';
- $result = ReadHeapProfile($prog, *PROFILE, $header);
- } elsif ($header =~ m/^heap profile:/) {
- $main::profile_type = 'heap';
- $result = ReadHeapProfile($prog, *PROFILE, $header);
- } elsif ($header =~ m/^--- *$contention_marker/o) {
- $main::profile_type = 'contention';
- $result = ReadSynchProfile($prog, *PROFILE);
- } elsif ($header =~ m/^--- *Stacks:/) {
- print STDERR
- "Old format contention profile: mistakenly reports " .
- "condition variable signals as lock contentions.\n";
- $main::profile_type = 'contention';
- $result = ReadSynchProfile($prog, *PROFILE);
- } elsif ($header =~ m/^--- *$profile_marker/) {
- # the binary cpu profile data starts immediately after this line
- $main::profile_type = 'cpu';
- $result = ReadCPUProfile($prog, $fname, *PROFILE);
- } else {
- if (defined($symbols)) {
- # a symbolized profile contains a format we don't recognize, bail out
- error("$fname: Cannot recognize profile section after symbols.\n");
- }
- # no ascii header present -- must be a CPU profile
- $main::profile_type = 'cpu';
- $result = ReadCPUProfile($prog, $fname, *PROFILE);
- }
-
- close(PROFILE);
-
- # if we got symbols along with the profile, return those as well
- if (defined($symbols)) {
- $result->{symbols} = $symbols;
- }
-
- return $result;
-}
-
-# Subtract one from caller pc so we map back to call instr.
-# However, don't do this if we're reading a symbolized profile
-# file, in which case the subtract-one was done when the file
-# was written.
-#
-# We apply the same logic to all readers, though ReadCPUProfile uses an
-# independent implementation.
-sub FixCallerAddresses {
- my $stack = shift;
- if ($main::use_symbolized_profile) {
- return $stack;
- } else {
- $stack =~ /(\s)/;
- my $delimiter = $1;
- my @addrs = split(' ', $stack);
- my @fixedaddrs;
- $#fixedaddrs = $#addrs;
- if ($#addrs >= 0) {
- $fixedaddrs[0] = $addrs[0];
- }
- for (my $i = 1; $i <= $#addrs; $i++) {
- $fixedaddrs[$i] = AddressSub($addrs[$i], "0x1");
- }
- return join $delimiter, @fixedaddrs;
- }
-}
-
-# CPU profile reader
-sub ReadCPUProfile {
- my $prog = shift;
- my $fname = shift; # just used for logging
- local *PROFILE = shift;
- my $version;
- my $period;
- my $i;
- my $profile = {};
- my $pcs = {};
-
- # Parse string into array of slots.
- my $slots = CpuProfileStream->new(*PROFILE, $fname);
-
- # Read header. The current header version is a 5-element structure
- # containing:
- # 0: header count (always 0)
- # 1: header "words" (after this one: 3)
- # 2: format version (0)
- # 3: sampling period (usec)
- # 4: unused padding (always 0)
- if ($slots->get(0) != 0 ) {
- error("$fname: not a profile file, or old format profile file\n");
- }
- $i = 2 + $slots->get(1);
- $version = $slots->get(2);
- $period = $slots->get(3);
- # Do some sanity checking on these header values.
- if ($version > (2**32) || $period > (2**32) || $i > (2**32) || $i < 5) {
- error("$fname: not a profile file, or corrupted profile file\n");
- }
-
- # Parse profile
- while ($slots->get($i) != -1) {
- my $n = $slots->get($i++);
- my $d = $slots->get($i++);
- if ($d > (2**16)) { # TODO(csilvers): what's a reasonable max-stack-depth?
- my $addr = sprintf("0%o", $i * ($address_length == 8 ? 4 : 8));
- print STDERR "At index $i (address $addr):\n";
- error("$fname: stack trace depth >= 2**32\n");
- }
- if ($slots->get($i) == 0) {
- # End of profile data marker
- $i += $d;
- last;
- }
-
- # Make key out of the stack entries
- my @k = ();
- for (my $j = 0; $j < $d; $j++) {
- my $pc = $slots->get($i+$j);
- # Subtract one from caller pc so we map back to call instr.
- # However, don't do this if we're reading a symbolized profile
- # file, in which case the subtract-one was done when the file
- # was written.
- if ($j > 0 && !$main::use_symbolized_profile) {
- $pc--;
- }
- $pc = sprintf("%0*x", $address_length, $pc);
- $pcs->{$pc} = 1;
- push @k, $pc;
- }
-
- AddEntry($profile, (join "\n", @k), $n);
- $i += $d;
- }
-
- # Parse map
- my $map = '';
- seek(PROFILE, $i * ($address_length / 2), 0);
- read(PROFILE, $map, (stat PROFILE)[7]);
-
- my $r = {};
- $r->{version} = $version;
- $r->{period} = $period;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
-
- return $r;
-}
-
-sub ReadHeapProfile {
- my $prog = shift;
- local *PROFILE = shift;
- my $header = shift;
-
- my $index = 1;
- if ($main::opt_inuse_space) {
- $index = 1;
- } elsif ($main::opt_inuse_objects) {
- $index = 0;
- } elsif ($main::opt_alloc_space) {
- $index = 3;
- } elsif ($main::opt_alloc_objects) {
- $index = 2;
- }
-
- # Find the type of this profile. The header line looks like:
- # heap profile: 1246: 8800744 [ 1246: 8800744] @ <heap-url>/266053
- # There are two pairs <count: size>, the first inuse objects/space, and the
- # second allocated objects/space. This is followed optionally by a profile
- # type, and if that is present, optionally by a sampling frequency.
- # For remote heap profiles (v1):
- # The interpretation of the sampling frequency is that the profiler, for
- # each sample, calculates a uniformly distributed random integer less than
- # the given value, and records the next sample after that many bytes have
- # been allocated. Therefore, the expected sample interval is half of the
- # given frequency. By default, if not specified, the expected sample
- # interval is 128KB. Only remote-heap-page profiles are adjusted for
- # sample size.
- # For remote heap profiles (v2):
- # The sampling frequency is the rate of a Poisson process. This means that
- # the probability of sampling an allocation of size X with sampling rate Y
- # is 1 - exp(-X/Y)
- # For version 2, a typical header line might look like this:
- # heap profile: 1922: 127792360 [ 1922: 127792360] @ <heap-url>_v2/524288
- # the trailing number (524288) is the sampling rate. (Version 1 showed
- # double the 'rate' here)
- my $sampling_algorithm = 0;
- my $sample_adjustment = 0;
- chomp($header);
- my $type = "unknown";
- if ($header =~ m"^heap profile:\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\](\s*@\s*([^/]*)(/(\d+))?)?") {
- if (defined($6) && ($6 ne '')) {
- $type = $6;
- my $sample_period = $8;
- # $type is "heapprofile" for profiles generated by the
- # heap-profiler, and either "heap" or "heap_v2" for profiles
- # generated by sampling directly within tcmalloc. It can also
- # be "growth" for heap-growth profiles. The first is typically
- # found for profiles generated locally, and the others for
- # remote profiles.
- if (($type eq "heapprofile") || ($type !~ /heap/) ) {
- # No need to adjust for the sampling rate with heap-profiler-derived data
- $sampling_algorithm = 0;
- } elsif ($type =~ /_v2/) {
- $sampling_algorithm = 2; # version 2 sampling
- if (defined($sample_period) && ($sample_period ne '')) {
- $sample_adjustment = int($sample_period);
- }
- } else {
- $sampling_algorithm = 1; # version 1 sampling
- if (defined($sample_period) && ($sample_period ne '')) {
- $sample_adjustment = int($sample_period)/2;
- }
- }
- } else {
- # We detect whether or not this is a remote-heap profile by checking
- # that the total-allocated stats ($n2,$s2) are exactly the
- # same as the in-use stats ($n1,$s1). It is remotely conceivable
- # that a non-remote-heap profile may pass this check, but it is hard
- # to imagine how that could happen.
- # In this case it's so old it's guaranteed to be remote-heap version 1.
- my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);
- if (($n1 == $n2) && ($s1 == $s2)) {
- # This is likely to be a remote-heap based sample profile
- $sampling_algorithm = 1;
- }
- }
- }
-
- if ($sampling_algorithm > 0) {
- # For remote-heap generated profiles, adjust the counts and sizes to
- # account for the sample rate (we sample once every 128KB by default).
- if ($sample_adjustment == 0) {
- # Turn on profile adjustment.
- $sample_adjustment = 128*1024;
- print STDERR "Adjusting heap profiles for 1-in-128KB sampling rate\n";
- } else {
- printf STDERR ("Adjusting heap profiles for 1-in-%d sampling rate\n",
- $sample_adjustment);
- }
- if ($sampling_algorithm > 1) {
- # We don't bother printing anything for the original version (version 1)
- printf STDERR "Heap version $sampling_algorithm\n";
- }
- }
-
- my $profile = {};
- my $pcs = {};
- my $map = "";
-
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- if (/^MAPPED_LIBRARIES:/) {
- # Read the /proc/self/maps data
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $map .= $_;
- }
- last;
- }
-
- if (/^--- Memory map:/) {
- # Read /proc/self/maps data as formatted by DumpAddressMap()
- my $buildvar = "";
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Parse "build=<dir>" specification if supplied
- if (m/^\s*build=(.*)\n/) {
- $buildvar = $1;
- }
-
- # Expand "$build" variable if available
- $_ =~ s/\$build\b/$buildvar/g;
-
- $map .= $_;
- }
- last;
- }
-
- # Read entry of the form:
- # <count1>: <bytes1> [<count2>: <bytes2>] @ a1 a2 a3 ... an
- s/^\s*//;
- s/\s*$//;
- if (m/^\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\]\s+@\s+(.*)$/) {
- my $stack = $5;
- my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);
-
- if ($sample_adjustment) {
- if ($sampling_algorithm == 2) {
- # Remote-heap version 2
- # The sampling frequency is the rate of a Poisson process.
- # This means that the probability of sampling an allocation of
- # size X with sampling rate Y is 1 - exp(-X/Y)
- if ($n1 != 0) {
- my $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
- my $scale_factor = 1/(1 - exp(-$ratio));
- $n1 *= $scale_factor;
- $s1 *= $scale_factor;
- }
- if ($n2 != 0) {
- my $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
- my $scale_factor = 1/(1 - exp(-$ratio));
- $n2 *= $scale_factor;
- $s2 *= $scale_factor;
- }
- } else {
- # Remote-heap version 1
- my $ratio;
- $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
- if ($ratio < 1) {
- $n1 /= $ratio;
- $s1 /= $ratio;
- }
- $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
- if ($ratio < 1) {
- $n2 /= $ratio;
- $s2 /= $ratio;
- }
- }
- }
-
- my @counts = ($n1, $s1, $n2, $s2);
- $stack = FixCallerAddresses($stack);
- push @stackTraces, "$n1 $s1 $n2 $s2 $stack";
- AddEntries($profile, $pcs, $stack, $counts[$index]);
- }
- }
-
- my $r = {};
- $r->{version} = "heap";
- $r->{period} = 1;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
- return $r;
-}
-
-sub ReadSynchProfile {
- my $prog = shift;
- local *PROFILE = shift;
- my $header = shift;
-
- my $map = '';
- my $profile = {};
- my $pcs = {};
- my $sampling_period = 1;
- my $cyclespernanosec = 2.8; # Default assumption for old binaries
- my $seen_clockrate = 0;
- my $line;
-
- my $index = 0;
- if ($main::opt_total_delay) {
- $index = 0;
- } elsif ($main::opt_contentions) {
- $index = 1;
- } elsif ($main::opt_mean_delay) {
- $index = 2;
- }
-
- while ( $line = <PROFILE> ) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- if ( $line =~ /^\s*(\d+)\s+(\d+) \@\s*(.*?)\s*$/ ) {
- my ($cycles, $count, $stack) = ($1, $2, $3);
-
- # Convert cycles to nanoseconds
- $cycles /= $cyclespernanosec;
-
- # Adjust for sampling done by application
- $cycles *= $sampling_period;
- $count *= $sampling_period;
-
- my @values = ($cycles, $count, $cycles / $count);
- AddEntries($profile, $pcs, FixCallerAddresses($stack), $values[$index]);
-
- } elsif ( $line =~ /^(slow release).*thread \d+ \@\s*(.*?)\s*$/ ||
- $line =~ /^\s*(\d+) \@\s*(.*?)\s*$/ ) {
- my ($cycles, $stack) = ($1, $2);
- if ($cycles !~ /^\d+$/) {
- next;
- }
-
- # Convert cycles to nanoseconds
- $cycles /= $cyclespernanosec;
-
- # Adjust for sampling done by application
- $cycles *= $sampling_period;
-
- AddEntries($profile, $pcs, FixCallerAddresses($stack), $cycles);
-
- } elsif ( $line =~ m/^([a-z][^=]*)=(.*)$/ ) {
- my ($variable, $value) = ($1,$2);
- for ($variable, $value) {
- s/^\s+//;
- s/\s+$//;
- }
- if ($variable eq "cycles/second") {
- $cyclespernanosec = $value / 1e9;
- $seen_clockrate = 1;
- } elsif ($variable eq "sampling period") {
- $sampling_period = $value;
- } elsif ($variable eq "ms since reset") {
- # Currently nothing is done with this value in pprof
- # So we just silently ignore it for now
- } elsif ($variable eq "discarded samples") {
- # Currently nothing is done with this value in pprof
- # So we just silently ignore it for now
- } else {
- printf STDERR ("Ignoring unnknown variable in /contention output: " .
- "'%s' = '%s'\n",$variable,$value);
- }
- } else {
- # Memory map entry
- $map .= $line;
- }
- }
-
- if (!$seen_clockrate) {
- printf STDERR ("No cycles/second entry in profile; Guessing %.1f GHz\n",
- $cyclespernanosec);
- }
-
- my $r = {};
- $r->{version} = 0;
- $r->{period} = $sampling_period;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
- return $r;
-}
-
-# Given a hex value in the form "0x1abcd" or "1abcd", return either
-# "0001abcd" or "000000000001abcd", depending on the current (global)
-# address length.
-sub HexExtend {
- my $addr = shift;
-
- $addr =~ s/^(0x)?0*//;
- my $zeros_needed = $address_length - length($addr);
- if ($zeros_needed < 0) {
- printf STDERR "Warning: address $addr is longer than address length $address_length\n";
- return $addr;
- }
- return ("0" x $zeros_needed) . $addr;
-}
-
-##### Symbol extraction #####
-
-# Aggressively search the lib_prefix values for the given library
-# If all else fails, just return the name of the library unmodified.
-# If the lib_prefix is "/my/path,/other/path" and $file is "/lib/dir/mylib.so"
-# it will search the following locations in this order, until it finds a file:
-# /my/path/lib/dir/mylib.so
-# /other/path/lib/dir/mylib.so
-# /my/path/dir/mylib.so
-# /other/path/dir/mylib.so
-# /my/path/mylib.so
-# /other/path/mylib.so
-# /lib/dir/mylib.so (returned as last resort)
-sub FindLibrary {
- my $file = shift;
- my $suffix = $file;
-
- # Search for the library as described above
- do {
- foreach my $prefix (@prefix_list) {
- my $fullpath = $prefix . $suffix;
- if (-e $fullpath) {
- return $fullpath;
- }
- }
- } while ($suffix =~ s|^/[^/]+/|/|);
- return $file;
-}
-
-# Return path to library with debugging symbols.
-# For libc libraries, the copy in /usr/lib/debug contains debugging symbols
-sub DebuggingLibrary {
- my $file = shift;
- if ($file =~ m|^/| && -f "/usr/lib/debug$file") {
- return "/usr/lib/debug$file";
- }
- if ($file =~ m|^/| && -f "/usr/lib/debug$file.debug") {
- return "/usr/lib/debug$file.debug";
- }
- return undef;
-}
-
-# Parse text section header of a library using objdump
-sub ParseTextSectionHeaderFromObjdump {
- my $lib = shift;
-
- my $size = undef;
- my $vma;
- my $file_offset;
- # Get objdump output from the library file to figure out how to
- # map between mapped addresses and addresses in the library.
- my $cmd = ShellEscape($obj_tool_map{"objdump"}, "-h", $lib);
- open(OBJDUMP, "$cmd |") || error("$cmd: $!\n");
- while (<OBJDUMP>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Idx Name Size VMA LMA File off Algn
- # 10 .text 00104b2c 420156f0 420156f0 000156f0 2**4
- # For 64-bit objects, VMA and LMA will be 16 hex digits, size and file
- # offset may still be 8. But AddressSub below will still handle that.
- my @x = split;
- if (($#x >= 6) && ($x[1] eq '.text')) {
- $size = $x[2];
- $vma = $x[3];
- $file_offset = $x[5];
- last;
- }
- }
- close(OBJDUMP);
-
- if (!defined($size)) {
- return undef;
- }
-
- my $r = {};
- $r->{size} = $size;
- $r->{vma} = $vma;
- $r->{file_offset} = $file_offset;
-
- return $r;
-}
-
-# Parse text section header of a library using otool (on OS X)
-sub ParseTextSectionHeaderFromOtool {
- my $lib = shift;
-
- my $size = undef;
- my $vma = undef;
- my $file_offset = undef;
- # Get otool output from the library file to figure out how to
- # map between mapped addresses and addresses in the library.
- my $command = ShellEscape($obj_tool_map{"otool"}, "-l", $lib);
- open(OTOOL, "$command |") || error("$command: $!\n");
- my $cmd = "";
- my $sectname = "";
- my $segname = "";
- foreach my $line (<OTOOL>) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- # Load command <#>
- # cmd LC_SEGMENT
- # [...]
- # Section
- # sectname __text
- # segname __TEXT
- # addr 0x000009f8
- # size 0x00018b9e
- # offset 2552
- # align 2^2 (4)
- # We will need to strip off the leading 0x from the hex addresses,
- # and convert the offset into hex.
- if ($line =~ /Load command/) {
- $cmd = "";
- $sectname = "";
- $segname = "";
- } elsif ($line =~ /Section/) {
- $sectname = "";
- $segname = "";
- } elsif ($line =~ /cmd (\w+)/) {
- $cmd = $1;
- } elsif ($line =~ /sectname (\w+)/) {
- $sectname = $1;
- } elsif ($line =~ /segname (\w+)/) {
- $segname = $1;
- } elsif (!(($cmd eq "LC_SEGMENT" || $cmd eq "LC_SEGMENT_64") &&
- $sectname eq "__text" &&
- $segname eq "__TEXT")) {
- next;
- } elsif ($line =~ /\baddr 0x([0-9a-fA-F]+)/) {
- $vma = $1;
- } elsif ($line =~ /\bsize 0x([0-9a-fA-F]+)/) {
- $size = $1;
- } elsif ($line =~ /\boffset ([0-9]+)/) {
- $file_offset = sprintf("%016x", $1);
- }
- if (defined($vma) && defined($size) && defined($file_offset)) {
- last;
- }
- }
- close(OTOOL);
-
- if (!defined($vma) || !defined($size) || !defined($file_offset)) {
- return undef;
- }
-
- my $r = {};
- $r->{size} = $size;
- $r->{vma} = $vma;
- $r->{file_offset} = $file_offset;
-
- return $r;
-}
-
-sub ParseTextSectionHeader {
- # obj_tool_map("otool") is only defined if we're in a Mach-O environment
- if (defined($obj_tool_map{"otool"})) {
- my $r = ParseTextSectionHeaderFromOtool(@_);
- if (defined($r)){
- return $r;
- }
- }
- # If otool doesn't work, or we don't have it, fall back to objdump
- return ParseTextSectionHeaderFromObjdump(@_);
-}
-
-# Split /proc/pid/maps dump into a list of libraries
-sub ParseLibraries {
- return if $main::use_symbol_page; # We don't need libraries info.
- my $prog = Cwd::abs_path(shift);
- my $map = shift;
- my $pcs = shift;
-
- my $result = [];
- my $h = "[a-f0-9]+";
- my $zero_offset = HexExtend("0");
-
- my $buildvar = "";
- my $priorlib = "";
- foreach my $l (split("\n", $map)) {
- if ($l =~ m/^\s*build=(.*)$/) {
- $buildvar = $1;
- }
-
- my $start;
- my $finish;
- my $offset;
- my $lib;
- if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(.+\.(so|dll|dylib|bundle)((\.\d+)+\w*(\.\d+){0,3})?)$/i) {
- # Full line from /proc/self/maps. Example:
- # 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so
- $start = HexExtend($1);
- $finish = HexExtend($2);
- $offset = HexExtend($3);
- $lib = $4;
- $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths
- } elsif ($l =~ /^\s*($h)-($h):\s*(\S+\.so(\.\d+)*)/) {
- # Cooked line from DumpAddressMap. Example:
- # 40000000-40015000: /lib/ld-2.3.2.so
- $start = HexExtend($1);
- $finish = HexExtend($2);
- $offset = $zero_offset;
- $lib = $3;
- } elsif (($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+)$/i) && ($4 eq $prog)) {
- # PIEs and address space randomization do not play well with our
- # default assumption that main executable is at lowest
- # addresses. So we're detecting main executable in
- # /proc/self/maps as well.
- $start = HexExtend($1);
- $finish = HexExtend($2);
- $offset = HexExtend($3);
- $lib = $4;
- $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths
- } else {
- next;
- }
-
- # Expand "$build" variable if available
- $lib =~ s/\$build\b/$buildvar/g;
-
- $lib = FindLibrary($lib);
-
- # Check for pre-relocated libraries, which use pre-relocated symbol tables
- # and thus require adjusting the offset that we'll use to translate
- # VM addresses into symbol table addresses.
- # Only do this if we're not going to fetch the symbol table from a
- # debugging copy of the library.
- if (!DebuggingLibrary($lib)) {
- my $text = ParseTextSectionHeader($lib);
- if (defined($text)) {
- my $vma_offset = AddressSub($text->{vma}, $text->{file_offset});
- $offset = AddressAdd($offset, $vma_offset);
- }
- }
-
- # If we find multiple executable segments for a single library, merge them
- # into a single entry that spans the complete address range.
- if ($lib eq $priorlib) {
- my $prior = pop(@{$result});
- $start = @$prior[1];
- # TODO $offset may be wrong if .text is not in the final segment.
- }
-
- push(@{$result}, [$lib, $start, $finish, $offset]);
- $priorlib = $lib;
- }
-
- # Append special entry for additional library (not relocated)
- if ($main::opt_lib ne "") {
- my $text = ParseTextSectionHeader($main::opt_lib);
- if (defined($text)) {
- my $start = $text->{vma};
- my $finish = AddressAdd($start, $text->{size});
-
- push(@{$result}, [$main::opt_lib, $start, $finish, $start]);
- }
- }
-
- # Append special entry for the main program. This covers
- # 0..max_pc_value_seen, so that we assume pc values not found in one
- # of the library ranges will be treated as coming from the main
- # program binary.
- my $min_pc = HexExtend("0");
- my $max_pc = $min_pc; # find the maximal PC value in any sample
- foreach my $pc (keys(%{$pcs})) {
- if (HexExtend($pc) gt $max_pc) { $max_pc = HexExtend($pc); }
- }
- push(@{$result}, [$prog, $min_pc, $max_pc, $zero_offset]);
-
- return $result;
-}
-
-# Add two hex addresses of length $address_length.
-# Run pprof --test for unit test if this is changed.
-sub AddressAdd {
- my $addr1 = shift;
- my $addr2 = shift;
- my $sum;
-
- if ($address_length == 8) {
- # Perl doesn't cope with wraparound arithmetic, so do it explicitly:
- $sum = (hex($addr1)+hex($addr2)) % (0x10000000 * 16);
- return sprintf("%08x", $sum);
-
- } else {
- # Do the addition in 7-nibble chunks to trivialize carry handling.
-
- if ($main::opt_debug and $main::opt_test) {
- print STDERR "AddressAdd $addr1 + $addr2 = ";
- }
-
- my $a1 = substr($addr1,-7);
- $addr1 = substr($addr1,0,-7);
- my $a2 = substr($addr2,-7);
- $addr2 = substr($addr2,0,-7);
- $sum = hex($a1) + hex($a2);
- my $c = 0;
- if ($sum > 0xfffffff) {
- $c = 1;
- $sum -= 0x10000000;
- }
- my $r = sprintf("%07x", $sum);
-
- $a1 = substr($addr1,-7);
- $addr1 = substr($addr1,0,-7);
- $a2 = substr($addr2,-7);
- $addr2 = substr($addr2,0,-7);
- $sum = hex($a1) + hex($a2) + $c;
- $c = 0;
- if ($sum > 0xfffffff) {
- $c = 1;
- $sum -= 0x10000000;
- }
- $r = sprintf("%07x", $sum) . $r;
-
- $sum = hex($addr1) + hex($addr2) + $c;
- if ($sum > 0xff) { $sum -= 0x100; }
- $r = sprintf("%02x", $sum) . $r;
-
- if ($main::opt_debug and $main::opt_test) { print STDERR "$r\n"; }
-
- return $r;
- }
-}
-
-
-# Subtract two hex addresses of length $address_length.
-# Run pprof --test for unit test if this is changed.
-sub AddressSub {
- my $addr1 = shift;
- my $addr2 = shift;
- my $diff;
-
- if ($address_length == 8) {
- # Perl doesn't cope with wraparound arithmetic, so do it explicitly:
- $diff = (hex($addr1)-hex($addr2)) % (0x10000000 * 16);
- return sprintf("%08x", $diff);
-
- } else {
- # Do the addition in 7-nibble chunks to trivialize borrow handling.
- # if ($main::opt_debug) { print STDERR "AddressSub $addr1 - $addr2 = "; }
-
- my $a1 = hex(substr($addr1,-7));
- $addr1 = substr($addr1,0,-7);
- my $a2 = hex(substr($addr2,-7));
- $addr2 = substr($addr2,0,-7);
- my $b = 0;
- if ($a2 > $a1) {
- $b = 1;
- $a1 += 0x10000000;
- }
- $diff = $a1 - $a2;
- my $r = sprintf("%07x", $diff);
-
- $a1 = hex(substr($addr1,-7));
- $addr1 = substr($addr1,0,-7);
- $a2 = hex(substr($addr2,-7)) + $b;
- $addr2 = substr($addr2,0,-7);
- $b = 0;
- if ($a2 > $a1) {
- $b = 1;
- $a1 += 0x10000000;
- }
- $diff = $a1 - $a2;
- $r = sprintf("%07x", $diff) . $r;
-
- $a1 = hex($addr1);
- $a2 = hex($addr2) + $b;
- if ($a2 > $a1) { $a1 += 0x100; }
- $diff = $a1 - $a2;
- $r = sprintf("%02x", $diff) . $r;
-
- # if ($main::opt_debug) { print STDERR "$r\n"; }
-
- return $r;
- }
-}
-
-# Increment a hex addresses of length $address_length.
-# Run pprof --test for unit test if this is changed.
-sub AddressInc {
- my $addr = shift;
- my $sum;
-
- if ($address_length == 8) {
- # Perl doesn't cope with wraparound arithmetic, so do it explicitly:
- $sum = (hex($addr)+1) % (0x10000000 * 16);
- return sprintf("%08x", $sum);
-
- } else {
- # Do the addition in 7-nibble chunks to trivialize carry handling.
- # We are always doing this to step through the addresses in a function,
- # and will almost never overflow the first chunk, so we check for this
- # case and exit early.
-
- # if ($main::opt_debug) { print STDERR "AddressInc $addr1 = "; }
-
- my $a1 = substr($addr,-7);
- $addr = substr($addr,0,-7);
- $sum = hex($a1) + 1;
- my $r = sprintf("%07x", $sum);
- if ($sum <= 0xfffffff) {
- $r = $addr . $r;
- # if ($main::opt_debug) { print STDERR "$r\n"; }
- return HexExtend($r);
- } else {
- $r = "0000000";
- }
-
- $a1 = substr($addr,-7);
- $addr = substr($addr,0,-7);
- $sum = hex($a1) + 1;
- $r = sprintf("%07x", $sum) . $r;
- if ($sum <= 0xfffffff) {
- $r = $addr . $r;
- # if ($main::opt_debug) { print STDERR "$r\n"; }
- return HexExtend($r);
- } else {
- $r = "00000000000000";
- }
-
- $sum = hex($addr) + 1;
- if ($sum > 0xff) { $sum -= 0x100; }
- $r = sprintf("%02x", $sum) . $r;
-
- # if ($main::opt_debug) { print STDERR "$r\n"; }
- return $r;
- }
-}
-
-# Extract symbols for all PC values found in profile
-sub ExtractSymbols {
- my $libs = shift;
- my $pcset = shift;
-
- my $symbols = {};
-
- # Map each PC value to the containing library. To make this faster,
- # we sort libraries by their starting pc value (highest first), and
- # advance through the libraries as we advance the pc. Sometimes the
- # addresses of libraries may overlap with the addresses of the main
- # binary, so to make sure the libraries 'win', we iterate over the
- # libraries in reverse order (which assumes the binary doesn't start
- # in the middle of a library, which seems a fair assumption).
- my @pcs = (sort { $a cmp $b } keys(%{$pcset})); # pcset is 0-extended strings
- foreach my $lib (sort {$b->[1] cmp $a->[1]} @{$libs}) {
- my $libname = $lib->[0];
- my $start = $lib->[1];
- my $finish = $lib->[2];
- my $offset = $lib->[3];
-
- # Get list of pcs that belong in this library.
- my $contained = [];
- my ($start_pc_index, $finish_pc_index);
- # Find smallest finish_pc_index such that $finish < $pc[$finish_pc_index].
- for ($finish_pc_index = $#pcs + 1; $finish_pc_index > 0;
- $finish_pc_index--) {
- last if $pcs[$finish_pc_index - 1] le $finish;
- }
- # Find smallest start_pc_index such that $start <= $pc[$start_pc_index].
- for ($start_pc_index = $finish_pc_index; $start_pc_index > 0;
- $start_pc_index--) {
- last if $pcs[$start_pc_index - 1] lt $start;
- }
- # This keeps PC values higher than $pc[$finish_pc_index] in @pcs,
- # in case there are overlaps in libraries and the main binary.
- @{$contained} = splice(@pcs, $start_pc_index,
- $finish_pc_index - $start_pc_index);
- # Map to symbols
- MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols);
- }
-
- return $symbols;
-}
-
-# Map list of PC values to symbols for a given image
-sub MapToSymbols {
- my $image = shift;
- my $offset = shift;
- my $pclist = shift;
- my $symbols = shift;
-
- my $debug = 0;
-
- # For libc (and other) libraries, the copy in /usr/lib/debug contains debugging symbols
- my $debugging = DebuggingLibrary($image);
- if ($debugging) {
- $image = $debugging;
- }
-
- # Ignore empty binaries
- if ($#{$pclist} < 0) { return; }
-
- # Figure out the addr2line command to use
- my $addr2line = $obj_tool_map{"addr2line"};
- my $cmd = ShellEscape($addr2line, "-f", "-C", "-e", $image);
- if (exists $obj_tool_map{"addr2line_pdb"}) {
- $addr2line = $obj_tool_map{"addr2line_pdb"};
- $cmd = ShellEscape($addr2line, "--demangle", "-f", "-C", "-e", $image);
- }
-
- # If "addr2line" isn't installed on the system at all, just use
- # nm to get what info we can (function names, but not line numbers).
- if (system(ShellEscape($addr2line, "--help") . " >$dev_null 2>&1") != 0) {
- MapSymbolsWithNM($image, $offset, $pclist, $symbols);
- return;
- }
-
- # "addr2line -i" can produce a variable number of lines per input
- # address, with no separator that allows us to tell when data for
- # the next address starts. So we find the address for a special
- # symbol (_fini) and interleave this address between all real
- # addresses passed to addr2line. The name of this special symbol
- # can then be used as a separator.
- $sep_address = undef; # May be filled in by MapSymbolsWithNM()
- my $nm_symbols = {};
- MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols);
- if (defined($sep_address)) {
- # Only add " -i" to addr2line if the binary supports it.
- # addr2line --help returns 0, but not if it sees an unknown flag first.
- if (system("$cmd -i --help >$dev_null 2>&1") == 0) {
- $cmd .= " -i";
- } else {
- $sep_address = undef; # no need for sep_address if we don't support -i
- }
- }
-
- # Make file with all PC values with intervening 'sep_address' so
- # that we can reliably detect the end of inlined function list
- open(ADDRESSES, ">$main::tmpfile_sym") || error("$main::tmpfile_sym: $!\n");
- if ($debug) { print("---- $image ---\n"); }
- for (my $i = 0; $i <= $#{$pclist}; $i++) {
- # addr2line always reads hex addresses, and does not need '0x' prefix.
- if ($debug) { printf STDERR ("%s\n", $pclist->[$i]); }
- printf ADDRESSES ("%s\n", AddressSub($pclist->[$i], $offset));
- if (defined($sep_address)) {
- printf ADDRESSES ("%s\n", $sep_address);
- }
- }
- close(ADDRESSES);
- if ($debug) {
- print("----\n");
- system("cat", $main::tmpfile_sym);
- print("---- $cmd ---\n");
- system("$cmd < " . ShellEscape($main::tmpfile_sym));
- print("----\n");
- }
-
- open(SYMBOLS, "$cmd <" . ShellEscape($main::tmpfile_sym) . " |")
- || error("$cmd: $!\n");
- my $count = 0; # Index in pclist
- while (<SYMBOLS>) {
- # Read fullfunction and filelineinfo from next pair of lines
- s/\r?\n$//g;
- my $fullfunction = $_;
- $_ = <SYMBOLS>;
- s/\r?\n$//g;
- my $filelinenum = $_;
-
- if (defined($sep_address) && $fullfunction eq $sep_symbol) {
- # Terminating marker for data for this address
- $count++;
- next;
- }
-
- $filelinenum =~ s|\\|/|g; # turn windows-style paths into unix-style paths
-
- # Remove discriminator markers as this comes after the line number and
- # confuses the rest of this script.
- $filelinenum =~ s/ \(discriminator \d+\)$//;
- # Convert unknown line numbers into line 0.
- $filelinenum =~ s/:\?$/:0/;
-
- my $pcstr = $pclist->[$count];
- my $function = ShortFunctionName($fullfunction);
- my $nms = $nm_symbols->{$pcstr};
- if (defined($nms)) {
- if ($fullfunction eq '??') {
- # nm found a symbol for us.
- $function = $nms->[0];
- $fullfunction = $nms->[2];
- } else {
- # MapSymbolsWithNM tags each routine with its starting address,
- # useful in case the image has multiple occurrences of this
- # routine. (It uses a syntax that resembles template paramters,
- # that are automatically stripped out by ShortFunctionName().)
- # addr2line does not provide the same information. So we check
- # if nm disambiguated our symbol, and if so take the annotated
- # (nm) version of the routine-name. TODO(csilvers): this won't
- # catch overloaded, inlined symbols, which nm doesn't see.
- # Better would be to do a check similar to nm's, in this fn.
- if ($nms->[2] =~ m/^\Q$function\E/) { # sanity check it's the right fn
- $function = $nms->[0];
- $fullfunction = $nms->[2];
- }
- }
- }
-
- # Prepend to accumulated symbols for pcstr
- # (so that caller comes before callee)
- my $sym = $symbols->{$pcstr};
- if (!defined($sym)) {
- $sym = [];
- $symbols->{$pcstr} = $sym;
- }
- unshift(@{$sym}, $function, $filelinenum, $fullfunction);
- if ($debug) { printf STDERR ("%s => [%s]\n", $pcstr, join(" ", @{$sym})); }
- if (!defined($sep_address)) {
- # Inlining is off, so this entry ends immediately
- $count++;
- }
- }
- close(SYMBOLS);
-}
-
-# Use nm to map the list of referenced PCs to symbols. Return true iff we
-# are able to read procedure information via nm.
-sub MapSymbolsWithNM {
- my $image = shift;
- my $offset = shift;
- my $pclist = shift;
- my $symbols = shift;
-
- # Get nm output sorted by increasing address
- my $symbol_table = GetProcedureBoundaries($image, ".");
- if (!%{$symbol_table}) {
- return 0;
- }
- # Start addresses are already the right length (8 or 16 hex digits).
- my @names = sort { $symbol_table->{$a}->[0] cmp $symbol_table->{$b}->[0] }
- keys(%{$symbol_table});
-
- if ($#names < 0) {
- # No symbols: just use addresses
- foreach my $pc (@{$pclist}) {
- my $pcstr = "0x" . $pc;
- $symbols->{$pc} = [$pcstr, "?", $pcstr];
- }
- return 0;
- }
-
- # Sort addresses so we can do a join against nm output
- my $index = 0;
- my $fullname = $names[0];
- my $name = ShortFunctionName($fullname);
- foreach my $pc (sort { $a cmp $b } @{$pclist}) {
- # Adjust for mapped offset
- my $mpc = AddressSub($pc, $offset);
- while (($index < $#names) && ($mpc ge $symbol_table->{$fullname}->[1])){
- $index++;
- $fullname = $names[$index];
- $name = ShortFunctionName($fullname);
- }
- if ($mpc lt $symbol_table->{$fullname}->[1]) {
- $symbols->{$pc} = [$name, "?", $fullname];
- } else {
- my $pcstr = "0x" . $pc;
- $symbols->{$pc} = [$pcstr, "?", $pcstr];
- }
- }
- return 1;
-}
-
-sub ShortFunctionName {
- my $function = shift;
- while ($function =~ s/\([^()]*\)(\s*const)?//g) { } # Argument types
- $function =~ s/<[0-9a-f]*>$//g; # Remove Address
- if (!$main::opt_no_strip_temp) {
- while ($function =~ s/<[^<>]*>//g) { } # Remove template arguments
- }
- $function =~ s/^.*\s+(\w+::)/$1/; # Remove leading type
- 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
-# argument is the program file being analyzed, and should be an ELF
-# 32-bit or ELF 64-bit executable file. The location of the tools
-# is determined by considering the following options in this order:
-# 1) --tools option, if set
-# 2) PPROF_TOOLS environment variable, if set
-# 3) the environment
-sub ConfigureObjTools {
- my $prog_file = shift;
-
- # Check for the existence of $prog_file because /usr/bin/file does not
- # predictably return error status in prod.
- (-e $prog_file) || error("$prog_file does not exist.\n");
-
- my $file_type = undef;
- if (-e "/usr/bin/file") {
- # Follow symlinks (at least for systems where "file" supports that).
- my $escaped_prog_file = ShellEscape($prog_file);
- $file_type = `/usr/bin/file -L $escaped_prog_file 2>$dev_null ||
- /usr/bin/file $escaped_prog_file`;
- } elsif ($^O == "MSWin32") {
- $file_type = "MS Windows";
- } else {
- print STDERR "WARNING: Can't determine the file type of $prog_file";
- }
-
- if ($file_type =~ /64-bit/) {
- # Change $address_length to 16 if the program file is ELF 64-bit.
- # We can't detect this from many (most?) heap or lock contention
- # profiles, since the actual addresses referenced are generally in low
- # memory even for 64-bit programs.
- $address_length = 16;
- }
-
- if ($file_type =~ /MS Windows/) {
- # For windows, we provide a version of nm and addr2line as part of
- # the opensource release, which is capable of parsing
- # Windows-style PDB executables. It should live in the path, or
- # in the same directory as pprof.
- $obj_tool_map{"nm_pdb"} = "nm-pdb";
- $obj_tool_map{"addr2line_pdb"} = "addr2line-pdb";
- }
-
- if ($file_type =~ /Mach-O/) {
- # OS X uses otool to examine Mach-O files, rather than objdump.
- $obj_tool_map{"otool"} = "otool";
- $obj_tool_map{"addr2line"} = "false"; # no addr2line
- $obj_tool_map{"objdump"} = "false"; # no objdump
- }
-
- # Go fill in %obj_tool_map with the pathnames to use:
- foreach my $tool (keys %obj_tool_map) {
- $obj_tool_map{$tool} = ConfigureTool($obj_tool_map{$tool});
- }
-}
-
-# Returns the path of a caller-specified object tool. If --tools or
-# PPROF_TOOLS are specified, then returns the full path to the tool
-# with that prefix. Otherwise, returns the path unmodified (which
-# means we will look for it on PATH).
-sub ConfigureTool {
- my $tool = shift;
- my $path;
-
- # --tools (or $PPROF_TOOLS) is a comma separated list, where each
- # item is either a) a pathname prefix, or b) a map of the form
- # <tool>:<path>. First we look for an entry of type (b) for our
- # tool. If one is found, we use it. Otherwise, we consider all the
- # pathname prefixes in turn, until one yields an existing file. If
- # none does, we use a default path.
- my $tools = $main::opt_tools || $ENV{"PPROF_TOOLS"} || "";
- if ($tools =~ m/(,|^)\Q$tool\E:([^,]*)/) {
- $path = $2;
- # TODO(csilvers): sanity-check that $path exists? Hard if it's relative.
- } elsif ($tools ne '') {
- foreach my $prefix (split(',', $tools)) {
- next if ($prefix =~ /:/); # ignore "tool:fullpath" entries in the list
- if (-x $prefix . $tool) {
- $path = $prefix . $tool;
- last;
- }
- }
- if (!$path) {
- error("No '$tool' found with prefix specified by " .
- "--tools (or \$PPROF_TOOLS) '$tools'\n");
- }
- } else {
- # ... otherwise use the version that exists in the same directory as
- # pprof. If there's nothing there, use $PATH.
- $0 =~ m,[^/]*$,; # this is everything after the last slash
- my $dirname = $`; # this is everything up to and including the last slash
- if (-x "$dirname$tool") {
- $path = "$dirname$tool";
- } else {
- $path = $tool;
- }
- }
- if ($main::opt_debug) { print STDERR "Using '$path' for '$tool'.\n"; }
- return $path;
-}
-
-sub ShellEscape {
- my @escaped_words = ();
- foreach my $word (@_) {
- my $escaped_word = $word;
- if ($word =~ m![^a-zA-Z0-9/.,_=-]!) { # check for anything not in whitelist
- $escaped_word =~ s/'/'\\''/;
- $escaped_word = "'$escaped_word'";
- }
- push(@escaped_words, $escaped_word);
- }
- return join(" ", @escaped_words);
-}
-
-sub cleanup {
- unlink($main::tmpfile_sym);
- unlink(keys %main::tempnames);
-
- # We leave any collected profiles in $HOME/pprof in case the user wants
- # to look at them later. We print a message informing them of this.
- if ((scalar(@main::profile_files) > 0) &&
- defined($main::collected_profile)) {
- if (scalar(@main::profile_files) == 1) {
- print STDERR "Dynamically gathered profile is in $main::collected_profile\n";
- }
- print STDERR "If you want to investigate this profile further, you can do:\n";
- print STDERR "\n";
- print STDERR " $0 \\\n";
- print STDERR " $main::prog \\\n";
- print STDERR " $main::collected_profile\n";
- print STDERR "\n";
- }
-}
-
-sub sighandler {
- cleanup();
- exit(1);
-}
-
-sub error {
- my $msg = shift;
- print STDERR $msg;
- cleanup();
- exit(1);
-}
-
-
-# Run $nm_command and get all the resulting procedure boundaries whose
-# names match "$regexp" and returns them in a hashtable mapping from
-# procedure name to a two-element vector of [start address, end address]
-sub GetProcedureBoundariesViaNm {
- my $escaped_nm_command = shift; # shell-escaped
- my $regexp = shift;
- my $image = shift;
-
- my $symbol_table = {};
- open(NM, "$escaped_nm_command |") || error("$escaped_nm_command: $!\n");
- my $last_start = "0";
- my $routine = "";
- while (<NM>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- if (m/^\s*([0-9a-f]+) (.) (..*)/) {
- my $start_val = $1;
- my $type = $2;
- my $this_routine = $3;
-
- # It's possible for two symbols to share the same address, if
- # one is a zero-length variable (like __start_google_malloc) or
- # one symbol is a weak alias to another (like __libc_malloc).
- # In such cases, we want to ignore all values except for the
- # actual symbol, which in nm-speak has type "T". The logic
- # below does this, though it's a bit tricky: what happens when
- # we have a series of lines with the same address, is the first
- # one gets queued up to be processed. However, it won't
- # *actually* be processed until later, when we read a line with
- # a different address. That means that as long as we're reading
- # lines with the same address, we have a chance to replace that
- # item in the queue, which we do whenever we see a 'T' entry --
- # that is, a line with type 'T'. If we never see a 'T' entry,
- # we'll just go ahead and process the first entry (which never
- # got touched in the queue), and ignore the others.
- if ($start_val eq $last_start && $type =~ /t/i) {
- # We are the 'T' symbol at this address, replace previous symbol.
- $routine = $this_routine;
- next;
- } elsif ($start_val eq $last_start) {
- # We're not the 'T' symbol at this address, so ignore us.
- next;
- }
-
- if ($this_routine eq $sep_symbol) {
- $sep_address = HexExtend($start_val);
- }
-
- # Tag this routine with the starting address in case the image
- # has multiple occurrences of this routine. We use a syntax
- # that resembles template paramters that are automatically
- # stripped out by ShortFunctionName()
- $this_routine .= "<$start_val>";
-
- if (defined($routine) && $routine =~ m/$regexp/) {
- $symbol_table->{$routine} = [HexExtend($last_start),
- HexExtend($start_val)];
- }
- $last_start = $start_val;
- $routine = $this_routine;
- } elsif (m/^Loaded image name: (.+)/) {
- # The win32 nm workalike emits information about the binary it is using.
- if ($main::opt_debug) { print STDERR "Using Image $1\n"; }
- } elsif (m/^PDB file name: (.+)/) {
- # The win32 nm workalike emits information about the pdb it is using.
- if ($main::opt_debug) { print STDERR "Using PDB $1\n"; }
- }
- }
- close(NM);
- # Handle the last line in the nm output. Unfortunately, we don't know
- # how big this last symbol is, because we don't know how big the file
- # is. For now, we just give it a size of 0.
- # TODO(csilvers): do better here.
- if (defined($routine) && $routine =~ m/$regexp/) {
- $symbol_table->{$routine} = [HexExtend($last_start),
- HexExtend($last_start)];
- }
-
- # Verify if addr2line can find the $sep_symbol. If not, we use objdump
- # to find the address for the $sep_symbol on code section which addr2line
- # can find.
- if (defined($sep_address)){
- my $start_val = $sep_address;
- my $addr2line = $obj_tool_map{"addr2line"};
- my $cmd = ShellEscape($addr2line, "-f", "-C", "-e", $image, "-i");
- open(FINI, "echo $start_val | $cmd |")
- || error("echo $start_val | $cmd: $!\n");
- $_ = <FINI>;
- s/\r?\n$//g;
- my $fini = $_;
- close(FINI);
- if ($fini ne $sep_symbol){
- my $objdump = $obj_tool_map{"objdump"};
- $cmd = ShellEscape($objdump, "-d", $image);
- my $grep = ShellEscape("grep", $sep_symbol);
- my $tail = ShellEscape("tail", "-n", "1");
- open(FINI, "$cmd | $grep | $tail |")
- || error("$cmd | $grep | $tail: $!\n");
- s/\r//g; # turn windows-looking lines into unix-looking lines
- my $data = <FINI>;
- if (defined($data)){
- ($start_val, $fini) = split(/ </,$data);
- }
- close(FINI);
- }
- $sep_address = HexExtend($start_val);
- }
-
- return $symbol_table;
-}
-
-# Gets the procedure boundaries for all routines in "$image" whose names
-# match "$regexp" and returns them in a hashtable mapping from procedure
-# name to a two-element vector of [start address, end address].
-# Will return an empty map if nm is not installed or not working properly.
-sub GetProcedureBoundaries {
- my $image = shift;
- my $regexp = shift;
-
- # If $image doesn't start with /, then put ./ in front of it. This works
- # around an obnoxious bug in our probing of nm -f behavior.
- # "nm -f $image" is supposed to fail on GNU nm, but if:
- #
- # a. $image starts with [BbSsPp] (for example, bin/foo/bar), AND
- # b. you have a.out in your current directory (a not uncommon occurrence)
- #
- # then "nm -f $image" succeeds because -f only looks at the first letter of
- # the argument, which looks valid because it's [BbSsPp], and then since
- # there's no image provided, it looks for a.out and finds it.
- #
- # This regex makes sure that $image starts with . or /, forcing the -f
- # parsing to fail since . and / are not valid formats.
- $image =~ s#^[^/]#./$&#;
-
- # For libc libraries, the copy in /usr/lib/debug contains debugging symbols
- my $debugging = DebuggingLibrary($image);
- if ($debugging) {
- $image = $debugging;
- }
-
- my $nm = $obj_tool_map{"nm"};
- my $cppfilt = $obj_tool_map{"c++filt"};
-
- # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm
- # binary doesn't support --demangle. In addition, for OS X we need
- # to use the -f flag to get 'flat' nm output (otherwise we don't sort
- # properly and get incorrect results). Unfortunately, GNU nm uses -f
- # in an incompatible way. So first we test whether our nm supports
- # --demangle and -f.
- my $demangle_flag = "";
- my $cppfilt_flag = "";
- my $to_devnull = ">$dev_null 2>&1";
- if (system(ShellEscape($nm, "--demangle", "image") . $to_devnull) == 0) {
- # In this mode, we do "nm --demangle <foo>"
- $demangle_flag = "--demangle";
- $cppfilt_flag = "";
- } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) {
- # In this mode, we do "nm <foo> | c++filt"
- $cppfilt_flag = " | " . ShellEscape($cppfilt);
- };
- my $flatten_flag = "";
- if (system(ShellEscape($nm, "-f", $image) . $to_devnull) == 0) {
- $flatten_flag = "-f";
- }
-
- # Finally, in the case $imagie isn't a debug library, we try again with
- # -D to at least get *exported* symbols. If we can't use --demangle,
- # we use c++filt instead, if it exists on this system.
- my @nm_commands = (ShellEscape($nm, "-n", $flatten_flag, $demangle_flag,
- $image) . " 2>$dev_null $cppfilt_flag",
- ShellEscape($nm, "-D", "-n", $flatten_flag, $demangle_flag,
- $image) . " 2>$dev_null $cppfilt_flag",
- # 6nm is for Go binaries
- ShellEscape("6nm", "$image") . " 2>$dev_null | sort",
- );
-
- # If the executable is an MS Windows PDB-format executable, we'll
- # have set up obj_tool_map("nm_pdb"). In this case, we actually
- # want to use both unix nm and windows-specific nm_pdb, since
- # PDB-format executables can apparently include dwarf .o files.
- if (exists $obj_tool_map{"nm_pdb"}) {
- push(@nm_commands,
- ShellEscape($obj_tool_map{"nm_pdb"}, "--demangle", $image)
- . " 2>$dev_null");
- }
-
- foreach my $nm_command (@nm_commands) {
- my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp, $image);
- return $symbol_table if (%{$symbol_table});
- }
- my $symbol_table = {};
- return $symbol_table;
-}
-
-
-# The test vectors for AddressAdd/Sub/Inc are 8-16-nibble hex strings.
-# To make them more readable, we add underscores at interesting places.
-# This routine removes the underscores, producing the canonical representation
-# used by pprof to represent addresses, particularly in the tested routines.
-sub CanonicalHex {
- my $arg = shift;
- return join '', (split '_',$arg);
-}
-
-
-# Unit test for AddressAdd:
-sub AddressAddUnitTest {
- my $test_data_8 = shift;
- my $test_data_16 = shift;
- my $error_count = 0;
- my $fail_count = 0;
- my $pass_count = 0;
- # print STDERR "AddressAddUnitTest: ", 1+$#{$test_data_8}, " tests\n";
-
- # First a few 8-nibble addresses. Note that this implementation uses
- # plain old arithmetic, so a quick sanity check along with verifying what
- # happens to overflow (we want it to wrap):
- $address_length = 8;
- foreach my $row (@{$test_data_8}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressAdd ($row->[0], $row->[1]);
- if ($sum ne $row->[2]) {
- printf STDERR "ERROR: %s != %s + %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[2];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressAdd 32-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count = $fail_count;
- $fail_count = 0;
- $pass_count = 0;
-
- # Now 16-nibble addresses.
- $address_length = 16;
- foreach my $row (@{$test_data_16}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressAdd (CanonicalHex($row->[0]), CanonicalHex($row->[1]));
- my $expected = join '', (split '_',$row->[2]);
- if ($sum ne CanonicalHex($row->[2])) {
- printf STDERR "ERROR: %s != %s + %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[2];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressAdd 64-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count += $fail_count;
-
- return $error_count;
-}
-
-
-# Unit test for AddressSub:
-sub AddressSubUnitTest {
- my $test_data_8 = shift;
- my $test_data_16 = shift;
- my $error_count = 0;
- my $fail_count = 0;
- my $pass_count = 0;
- # print STDERR "AddressSubUnitTest: ", 1+$#{$test_data_8}, " tests\n";
-
- # First a few 8-nibble addresses. Note that this implementation uses
- # plain old arithmetic, so a quick sanity check along with verifying what
- # happens to overflow (we want it to wrap):
- $address_length = 8;
- foreach my $row (@{$test_data_8}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressSub ($row->[0], $row->[1]);
- if ($sum ne $row->[3]) {
- printf STDERR "ERROR: %s != %s - %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[3];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressSub 32-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count = $fail_count;
- $fail_count = 0;
- $pass_count = 0;
-
- # Now 16-nibble addresses.
- $address_length = 16;
- foreach my $row (@{$test_data_16}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressSub (CanonicalHex($row->[0]), CanonicalHex($row->[1]));
- if ($sum ne CanonicalHex($row->[3])) {
- printf STDERR "ERROR: %s != %s - %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[3];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressSub 64-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count += $fail_count;
-
- return $error_count;
-}
-
-
-# Unit test for AddressInc:
-sub AddressIncUnitTest {
- my $test_data_8 = shift;
- my $test_data_16 = shift;
- my $error_count = 0;
- my $fail_count = 0;
- my $pass_count = 0;
- # print STDERR "AddressIncUnitTest: ", 1+$#{$test_data_8}, " tests\n";
-
- # First a few 8-nibble addresses. Note that this implementation uses
- # plain old arithmetic, so a quick sanity check along with verifying what
- # happens to overflow (we want it to wrap):
- $address_length = 8;
- foreach my $row (@{$test_data_8}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressInc ($row->[0]);
- if ($sum ne $row->[4]) {
- printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum,
- $row->[0], $row->[4];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressInc 32-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count = $fail_count;
- $fail_count = 0;
- $pass_count = 0;
-
- # Now 16-nibble addresses.
- $address_length = 16;
- foreach my $row (@{$test_data_16}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressInc (CanonicalHex($row->[0]));
- if ($sum ne CanonicalHex($row->[4])) {
- printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum,
- $row->[0], $row->[4];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressInc 64-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count += $fail_count;
-
- return $error_count;
-}
-
-
-# Driver for unit tests.
-# Currently just the address add/subtract/increment routines for 64-bit.
-sub RunUnitTests {
- my $error_count = 0;
-
- # This is a list of tuples [a, b, a+b, a-b, a+1]
- my $unit_test_data_8 = [
- [qw(aaaaaaaa 50505050 fafafafa 5a5a5a5a aaaaaaab)],
- [qw(50505050 aaaaaaaa fafafafa a5a5a5a6 50505051)],
- [qw(ffffffff aaaaaaaa aaaaaaa9 55555555 00000000)],
- [qw(00000001 ffffffff 00000000 00000002 00000002)],
- [qw(00000001 fffffff0 fffffff1 00000011 00000002)],
- ];
- my $unit_test_data_16 = [
- # The implementation handles data in 7-nibble chunks, so those are the
- # interesting boundaries.
- [qw(aaaaaaaa 50505050
- 00_000000f_afafafa 00_0000005_a5a5a5a 00_000000a_aaaaaab)],
- [qw(50505050 aaaaaaaa
- 00_000000f_afafafa ff_ffffffa_5a5a5a6 00_0000005_0505051)],
- [qw(ffffffff aaaaaaaa
- 00_000001a_aaaaaa9 00_0000005_5555555 00_0000010_0000000)],
- [qw(00000001 ffffffff
- 00_0000010_0000000 ff_ffffff0_0000002 00_0000000_0000002)],
- [qw(00000001 fffffff0
- 00_000000f_ffffff1 ff_ffffff0_0000011 00_0000000_0000002)],
-
- [qw(00_a00000a_aaaaaaa 50505050
- 00_a00000f_afafafa 00_a000005_a5a5a5a 00_a00000a_aaaaaab)],
- [qw(0f_fff0005_0505050 aaaaaaaa
- 0f_fff000f_afafafa 0f_ffefffa_5a5a5a6 0f_fff0005_0505051)],
- [qw(00_000000f_fffffff 01_800000a_aaaaaaa
- 01_800001a_aaaaaa9 fe_8000005_5555555 00_0000010_0000000)],
- [qw(00_0000000_0000001 ff_fffffff_fffffff
- 00_0000000_0000000 00_0000000_0000002 00_0000000_0000002)],
- [qw(00_0000000_0000001 ff_fffffff_ffffff0
- ff_fffffff_ffffff1 00_0000000_0000011 00_0000000_0000002)],
- ];
-
- $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16);
- $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16);
- $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16);
- if ($error_count > 0) {
- print STDERR $error_count, " errors: FAILED\n";
- } else {
- print STDERR "PASS\n";
- }
- exit ($error_count);
-}
diff --git a/src/third_party/gperftools-2.5/src/profile-handler.cc b/src/third_party/gperftools-2.5/src/profile-handler.cc
deleted file mode 100644
index 7fdcb69333f..00000000000
--- a/src/third_party/gperftools-2.5/src/profile-handler.cc
+++ /dev/null
@@ -1,584 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2009, 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
-// Nabeel Mian
-//
-// Implements management of profile timers and the corresponding signal handler.
-
-#include "config.h"
-#include "profile-handler.h"
-
-#if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
-
-#include <stdio.h>
-#include <errno.h>
-#include <sys/time.h>
-
-#include <list>
-#include <string>
-
-#if HAVE_LINUX_SIGEV_THREAD_ID
-// for timer_{create,settime} and associated typedefs & constants
-#include <time.h>
-// for sys_gettid
-#include "base/linux_syscall_support.h"
-// for perftools_pthread_key_create
-#include "maybe_threads.h"
-#endif
-
-#include "base/dynamic_annotations.h"
-#include "base/googleinit.h"
-#include "base/logging.h"
-#include "base/spinlock.h"
-#include "maybe_threads.h"
-
-using std::list;
-using std::string;
-
-// This structure is used by ProfileHandlerRegisterCallback and
-// ProfileHandlerUnregisterCallback as a handle to a registered callback.
-struct ProfileHandlerToken {
- // Sets the callback and associated arg.
- ProfileHandlerToken(ProfileHandlerCallback cb, void* cb_arg)
- : callback(cb),
- callback_arg(cb_arg) {
- }
-
- // Callback function to be invoked on receiving a profile timer interrupt.
- ProfileHandlerCallback callback;
- // Argument for the callback function.
- void* callback_arg;
-};
-
-// Blocks a signal from being delivered to the current thread while the object
-// is alive. Unblocks it upon destruction.
-class ScopedSignalBlocker {
- public:
- ScopedSignalBlocker(int signo) {
- sigemptyset(&sig_set_);
- sigaddset(&sig_set_, signo);
- RAW_CHECK(sigprocmask(SIG_BLOCK, &sig_set_, NULL) == 0,
- "sigprocmask (block)");
- }
- ~ScopedSignalBlocker() {
- RAW_CHECK(sigprocmask(SIG_UNBLOCK, &sig_set_, NULL) == 0,
- "sigprocmask (unblock)");
- }
-
- private:
- sigset_t sig_set_;
-};
-
-// This class manages profile timers and associated signal handler. This is a
-// a singleton.
-class ProfileHandler {
- public:
- // Registers the current thread with the profile handler.
- void RegisterThread();
-
- // Registers a callback routine to receive profile timer ticks. The returned
- // token is to be used when unregistering this callback and must not be
- // deleted by the caller.
- ProfileHandlerToken* RegisterCallback(ProfileHandlerCallback callback,
- void* callback_arg);
-
- // Unregisters a previously registered callback. Expects the token returned
- // by the corresponding RegisterCallback routine.
- void UnregisterCallback(ProfileHandlerToken* token)
- NO_THREAD_SAFETY_ANALYSIS;
-
- // Unregisters all the callbacks and stops the timer(s).
- void Reset();
-
- // Gets the current state of profile handler.
- void GetState(ProfileHandlerState* state);
-
- // Initializes and returns the ProfileHandler singleton.
- static ProfileHandler* Instance();
-
- private:
- ProfileHandler();
- ~ProfileHandler();
-
- // Largest allowed frequency.
- static const int32 kMaxFrequency = 4000;
- // Default frequency.
- static const int32 kDefaultFrequency = 100;
-
- // ProfileHandler singleton.
- static ProfileHandler* instance_;
-
- // pthread_once_t for one time initialization of ProfileHandler singleton.
- static pthread_once_t once_;
-
- // Initializes the ProfileHandler singleton via GoogleOnceInit.
- static void Init();
-
- // Timer state as configured previously.
- bool timer_running_;
-
- // The number of profiling signal interrupts received.
- int64 interrupts_ GUARDED_BY(signal_lock_);
-
- // Profiling signal interrupt frequency, read-only after construction.
- int32 frequency_;
-
- // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM).
- // Translated into an equivalent choice of clock if per_thread_timer_enabled_
- // is true.
- int timer_type_;
-
- // Signal number for timer signal.
- int signal_number_;
-
- // Counts the number of callbacks registered.
- int32 callback_count_ GUARDED_BY(control_lock_);
-
- // Is profiling allowed at all?
- bool allowed_;
-
- // Must be false if HAVE_LINUX_SIGEV_THREAD_ID is not defined.
- bool per_thread_timer_enabled_;
-
-#ifdef HAVE_LINUX_SIGEV_THREAD_ID
- // this is used to destroy per-thread profiling timers on thread
- // termination
- pthread_key_t thread_timer_key;
-#endif
-
- // This lock serializes the registration of threads and protects the
- // callbacks_ list below.
- // Locking order:
- // In the context of a signal handler, acquire signal_lock_ to walk the
- // callback list. Otherwise, acquire control_lock_, disable the signal
- // handler and then acquire signal_lock_.
- SpinLock control_lock_ ACQUIRED_BEFORE(signal_lock_);
- SpinLock signal_lock_;
-
- // Holds the list of registered callbacks. We expect the list to be pretty
- // small. Currently, the cpu profiler (base/profiler) and thread module
- // (base/thread.h) are the only two components registering callbacks.
- // Following are the locking requirements for callbacks_:
- // For read-write access outside the SIGPROF handler:
- // - Acquire control_lock_
- // - Disable SIGPROF handler.
- // - Acquire signal_lock_
- // For read-only access in the context of SIGPROF handler
- // (Read-write access is *not allowed* in the SIGPROF handler)
- // - Acquire signal_lock_
- // For read-only access outside SIGPROF handler:
- // - Acquire control_lock_
- typedef list<ProfileHandlerToken*> CallbackList;
- typedef CallbackList::iterator CallbackIterator;
- CallbackList callbacks_ GUARDED_BY(signal_lock_);
-
- // Starts or stops the interval timer.
- // Will ignore any requests to enable or disable when
- // per_thread_timer_enabled_ is true.
- void UpdateTimer(bool enable) EXCLUSIVE_LOCKS_REQUIRED(signal_lock_);
-
- // Returns true if the handler is not being used by something else.
- // This checks the kernel's signal handler table.
- bool IsSignalHandlerAvailable();
-
- // Signal handler. Iterates over and calls all the registered callbacks.
- static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext);
-
- DISALLOW_COPY_AND_ASSIGN(ProfileHandler);
-};
-
-ProfileHandler* ProfileHandler::instance_ = NULL;
-pthread_once_t ProfileHandler::once_ = PTHREAD_ONCE_INIT;
-
-const int32 ProfileHandler::kMaxFrequency;
-const int32 ProfileHandler::kDefaultFrequency;
-
-// If we are LD_PRELOAD-ed against a non-pthreads app, then these functions
-// won't be defined. We declare them here, for that case (with weak linkage)
-// which will cause the non-definition to resolve to NULL. We can then check
-// for NULL or not in Instance.
-extern "C" {
-int pthread_once(pthread_once_t *, void (*)(void)) ATTRIBUTE_WEAK;
-int pthread_kill(pthread_t thread_id, int signo) ATTRIBUTE_WEAK;
-
-#if HAVE_LINUX_SIGEV_THREAD_ID
-int timer_create(clockid_t clockid, struct sigevent* evp,
- timer_t* timerid) ATTRIBUTE_WEAK;
-int timer_delete(timer_t timerid) ATTRIBUTE_WEAK;
-int timer_settime(timer_t timerid, int flags, const struct itimerspec* value,
- struct itimerspec* ovalue) ATTRIBUTE_WEAK;
-#endif
-}
-
-#if HAVE_LINUX_SIGEV_THREAD_ID
-
-struct timer_id_holder {
- timer_t timerid;
- timer_id_holder(timer_t _timerid) : timerid(_timerid) {}
-};
-
-extern "C" {
- static void ThreadTimerDestructor(void *arg) {
- if (!arg) {
- return;
- }
- timer_id_holder *holder = static_cast<timer_id_holder *>(arg);
- timer_delete(holder->timerid);
- delete holder;
- }
-}
-
-static void CreateThreadTimerKey(pthread_key_t *pkey) {
- int rv = perftools_pthread_key_create(pkey, ThreadTimerDestructor);
- if (rv) {
- RAW_LOG(FATAL, "aborting due to pthread_key_create error: %s", strerror(rv));
- }
-}
-
-static void StartLinuxThreadTimer(int timer_type, int signal_number,
- int32 frequency, pthread_key_t timer_key) {
- int rv;
- struct sigevent sevp;
- timer_t timerid;
- struct itimerspec its;
- memset(&sevp, 0, sizeof(sevp));
- sevp.sigev_notify = SIGEV_THREAD_ID;
- sevp._sigev_un._tid = sys_gettid();
- sevp.sigev_signo = signal_number;
- clockid_t clock = CLOCK_THREAD_CPUTIME_ID;
- if (timer_type == ITIMER_REAL) {
- clock = CLOCK_MONOTONIC;
- }
- rv = timer_create(clock, &sevp, &timerid);
- if (rv) {
- RAW_LOG(FATAL, "aborting due to timer_create error: %s", strerror(errno));
- }
-
- timer_id_holder *holder = new timer_id_holder(timerid);
- rv = perftools_pthread_setspecific(timer_key, holder);
- if (rv) {
- RAW_LOG(FATAL, "aborting due to pthread_setspecific error: %s", strerror(rv));
- }
-
- its.it_interval.tv_sec = 0;
- its.it_interval.tv_nsec = 1000000000 / frequency;
- its.it_value = its.it_interval;
- rv = timer_settime(timerid, 0, &its, 0);
- if (rv) {
- RAW_LOG(FATAL, "aborting due to timer_settime error: %s", strerror(errno));
- }
-}
-#endif
-
-void ProfileHandler::Init() {
- instance_ = new ProfileHandler();
-}
-
-ProfileHandler* ProfileHandler::Instance() {
- if (pthread_once) {
- pthread_once(&once_, Init);
- }
- if (instance_ == NULL) {
- // This will be true on systems that don't link in pthreads,
- // including on FreeBSD where pthread_once has a non-zero address
- // (but doesn't do anything) even when pthreads isn't linked in.
- Init();
- assert(instance_ != NULL);
- }
- return instance_;
-}
-
-ProfileHandler::ProfileHandler()
- : timer_running_(false),
- interrupts_(0),
- callback_count_(0),
- allowed_(true),
- per_thread_timer_enabled_(false) {
- SpinLockHolder cl(&control_lock_);
-
- timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF);
- signal_number_ = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
-
- // Get frequency of interrupts (if specified)
- char junk;
- const char* fr = getenv("CPUPROFILE_FREQUENCY");
- if (fr != NULL && (sscanf(fr, "%u%c", &frequency_, &junk) == 1) &&
- (frequency_ > 0)) {
- // Limit to kMaxFrequency
- frequency_ = (frequency_ > kMaxFrequency) ? kMaxFrequency : frequency_;
- } else {
- frequency_ = kDefaultFrequency;
- }
-
- if (!allowed_) {
- return;
- }
-
-#if HAVE_LINUX_SIGEV_THREAD_ID
- // Do this early because we might be overriding signal number.
-
- const char *per_thread = getenv("CPUPROFILE_PER_THREAD_TIMERS");
- const char *signal_number = getenv("CPUPROFILE_TIMER_SIGNAL");
-
- if (per_thread || signal_number) {
- if (timer_create && pthread_once) {
- CreateThreadTimerKey(&thread_timer_key);
- per_thread_timer_enabled_ = true;
- // Override signal number if requested.
- if (signal_number) {
- signal_number_ = strtol(signal_number, NULL, 0);
- }
- } else {
- RAW_LOG(INFO,
- "Ignoring CPUPROFILE_PER_THREAD_TIMERS and\n"
- " CPUPROFILE_TIMER_SIGNAL due to lack of timer_create().\n"
- " Preload or link to librt.so for this to work");
- }
- }
-#endif
-
- // If something else is using the signal handler,
- // assume it has priority over us and stop.
- if (!IsSignalHandlerAvailable()) {
- RAW_LOG(INFO, "Disabling profiler because signal %d handler is already in use.",
- signal_number_);
- allowed_ = false;
- return;
- }
-
- // Install the signal handler.
- struct sigaction sa;
- sa.sa_sigaction = SignalHandler;
- sa.sa_flags = SA_RESTART | SA_SIGINFO;
- sigemptyset(&sa.sa_mask);
- RAW_CHECK(sigaction(signal_number_, &sa, NULL) == 0, "sigprof (enable)");
-}
-
-ProfileHandler::~ProfileHandler() {
- Reset();
-#ifdef HAVE_LINUX_SIGEV_THREAD_ID
- if (per_thread_timer_enabled_) {
- perftools_pthread_key_delete(thread_timer_key);
- }
-#endif
-}
-
-void ProfileHandler::RegisterThread() {
- SpinLockHolder cl(&control_lock_);
-
- if (!allowed_) {
- return;
- }
-
- // Record the thread identifier and start the timer if profiling is on.
- ScopedSignalBlocker block(signal_number_);
- SpinLockHolder sl(&signal_lock_);
-#if HAVE_LINUX_SIGEV_THREAD_ID
- if (per_thread_timer_enabled_) {
- StartLinuxThreadTimer(timer_type_, signal_number_, frequency_,
- thread_timer_key);
- return;
- }
-#endif
- UpdateTimer(callback_count_ > 0);
-}
-
-ProfileHandlerToken* ProfileHandler::RegisterCallback(
- ProfileHandlerCallback callback, void* callback_arg) {
-
- ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg);
-
- SpinLockHolder cl(&control_lock_);
- {
- ScopedSignalBlocker block(signal_number_);
- SpinLockHolder sl(&signal_lock_);
- callbacks_.push_back(token);
- ++callback_count_;
- UpdateTimer(true);
- }
- return token;
-}
-
-void ProfileHandler::UnregisterCallback(ProfileHandlerToken* token) {
- SpinLockHolder cl(&control_lock_);
- for (CallbackIterator it = callbacks_.begin(); it != callbacks_.end();
- ++it) {
- if ((*it) == token) {
- RAW_CHECK(callback_count_ > 0, "Invalid callback count");
- {
- ScopedSignalBlocker block(signal_number_);
- SpinLockHolder sl(&signal_lock_);
- delete *it;
- callbacks_.erase(it);
- --callback_count_;
- if (callback_count_ == 0)
- UpdateTimer(false);
- }
- return;
- }
- }
- // Unknown token.
- RAW_LOG(FATAL, "Invalid token");
-}
-
-void ProfileHandler::Reset() {
- SpinLockHolder cl(&control_lock_);
- {
- ScopedSignalBlocker block(signal_number_);
- SpinLockHolder sl(&signal_lock_);
- CallbackIterator it = callbacks_.begin();
- while (it != callbacks_.end()) {
- CallbackIterator tmp = it;
- ++it;
- delete *tmp;
- callbacks_.erase(tmp);
- }
- callback_count_ = 0;
- UpdateTimer(false);
- }
-}
-
-void ProfileHandler::GetState(ProfileHandlerState* state) {
- SpinLockHolder cl(&control_lock_);
- {
- ScopedSignalBlocker block(signal_number_);
- SpinLockHolder sl(&signal_lock_); // Protects interrupts_.
- state->interrupts = interrupts_;
- }
- state->frequency = frequency_;
- state->callback_count = callback_count_;
- state->allowed = allowed_;
-}
-
-void ProfileHandler::UpdateTimer(bool enable) {
- if (per_thread_timer_enabled_) {
- // Ignore any attempts to disable it because that's not supported, and it's
- // always enabled so enabling is always a NOP.
- return;
- }
-
- if (enable == timer_running_) {
- return;
- }
- timer_running_ = enable;
-
- struct itimerval timer;
- static const int kMillion = 1000000;
- int interval_usec = enable ? kMillion / frequency_ : 0;
- timer.it_interval.tv_sec = interval_usec / kMillion;
- timer.it_interval.tv_usec = interval_usec % kMillion;
- timer.it_value = timer.it_interval;
- setitimer(timer_type_, &timer, 0);
-}
-
-bool ProfileHandler::IsSignalHandlerAvailable() {
- struct sigaction sa;
- RAW_CHECK(sigaction(signal_number_, NULL, &sa) == 0, "is-signal-handler avail");
-
- // We only take over the handler if the current one is unset.
- // It must be SIG_IGN or SIG_DFL, not some other function.
- // SIG_IGN must be allowed because when profiling is allowed but
- // not actively in use, this code keeps the handler set to SIG_IGN.
- // That setting will be inherited across fork+exec. In order for
- // any child to be able to use profiling, SIG_IGN must be treated
- // as available.
- return sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL;
-}
-
-void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) {
- int saved_errno = errno;
- // At this moment, instance_ must be initialized because the handler is
- // enabled in RegisterThread or RegisterCallback only after
- // ProfileHandler::Instance runs.
- ProfileHandler* instance = ANNOTATE_UNPROTECTED_READ(instance_);
- RAW_CHECK(instance != NULL, "ProfileHandler is not initialized");
- {
- SpinLockHolder sl(&instance->signal_lock_);
- ++instance->interrupts_;
- for (CallbackIterator it = instance->callbacks_.begin();
- it != instance->callbacks_.end();
- ++it) {
- (*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg);
- }
- }
- errno = saved_errno;
-}
-
-// This module initializer registers the main thread, so it must be
-// executed in the context of the main thread.
-REGISTER_MODULE_INITIALIZER(profile_main, ProfileHandlerRegisterThread());
-
-void ProfileHandlerRegisterThread() {
- ProfileHandler::Instance()->RegisterThread();
-}
-
-ProfileHandlerToken* ProfileHandlerRegisterCallback(
- ProfileHandlerCallback callback, void* callback_arg) {
- return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg);
-}
-
-void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
- ProfileHandler::Instance()->UnregisterCallback(token);
-}
-
-void ProfileHandlerReset() {
- return ProfileHandler::Instance()->Reset();
-}
-
-void ProfileHandlerGetState(ProfileHandlerState* state) {
- ProfileHandler::Instance()->GetState(state);
-}
-
-#else // OS_CYGWIN
-
-// 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.
-void ProfileHandlerRegisterThread() {
-}
-
-ProfileHandlerToken* ProfileHandlerRegisterCallback(
- ProfileHandlerCallback callback, void* callback_arg) {
- return NULL;
-}
-
-void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
-}
-
-void ProfileHandlerReset() {
-}
-
-void ProfileHandlerGetState(ProfileHandlerState* state) {
-}
-
-#endif // OS_CYGWIN
diff --git a/src/third_party/gperftools-2.5/src/profile-handler.h b/src/third_party/gperftools-2.5/src/profile-handler.h
deleted file mode 100644
index 3eae169d55a..00000000000
--- a/src/third_party/gperftools-2.5/src/profile-handler.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2009, 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: Nabeel Mian
- *
- * This module manages the cpu profile timers and the associated interrupt
- * handler. When enabled, all threads in the program are profiled.
- *
- * Any component interested in receiving a profile timer interrupt can do so by
- * registering a callback. All registered callbacks must be async-signal-safe.
- *
- * Note: This module requires the sole ownership of the configured timer and
- * signal. The timer defaults to ITIMER_PROF, can be changed to ITIMER_REAL by
- * the environment variable CPUPROFILE_REALTIME, or is changed to a POSIX timer
- * with CPUPROFILE_PER_THREAD_TIMERS. The signal defaults to SIGPROF/SIGALRM to
- * match the choice of timer and can be set to an arbitrary value using
- * CPUPROFILE_TIMER_SIGNAL with CPUPROFILE_PER_THREAD_TIMERS.
- */
-
-#ifndef BASE_PROFILE_HANDLER_H_
-#define BASE_PROFILE_HANDLER_H_
-
-#include "config.h"
-#include <signal.h>
-#ifdef COMPILER_MSVC
-#include "conflict-signal.h"
-#endif
-#include "base/basictypes.h"
-
-/* Forward declaration. */
-struct ProfileHandlerToken;
-
-/*
- * Callback function to be used with ProfilefHandlerRegisterCallback. This
- * function will be called in the context of SIGPROF signal handler and must
- * be async-signal-safe. The first three arguments are the values provided by
- * the SIGPROF signal handler. We use void* to avoid using ucontext_t on
- * non-POSIX systems.
- *
- * Requirements:
- * - Callback must be async-signal-safe.
- * - None of the functions in ProfileHandler are async-signal-safe. Therefore,
- * callback function *must* not call any of the ProfileHandler functions.
- * - Callback is not required to be re-entrant. At most one instance of
- * callback can run at a time.
- *
- * Notes:
- * - The SIGPROF signal handler saves and restores errno, so the callback
- * doesn't need to.
- * - Callback code *must* not acquire lock(s) to serialize access to data shared
- * with the code outside the signal handler (callback must be
- * async-signal-safe). If such a serialization is needed, follow the model
- * used by profiler.cc:
- *
- * When code other than the signal handler modifies the shared data it must:
- * - Acquire lock.
- * - Unregister the callback with the ProfileHandler.
- * - Modify shared data.
- * - Re-register the callback.
- * - Release lock.
- * and the callback code gets a lockless, read-write access to the data.
- */
-typedef void (*ProfileHandlerCallback)(int sig, siginfo_t* sig_info,
- void* ucontext, void* callback_arg);
-
-/*
- * Registers a new thread with profile handler and should be called only once
- * per thread. The main thread is registered at program startup. This routine
- * is called by the Thread module in google3/thread whenever a new thread is
- * created. This function is not async-signal-safe.
- */
-void ProfileHandlerRegisterThread();
-
-/*
- * Registers a callback routine. This callback function will be called in the
- * context of SIGPROF handler, so must be async-signal-safe. The returned token
- * is to be used when unregistering this callback via
- * ProfileHandlerUnregisterCallback. Registering the first callback enables
- * the SIGPROF signal handler. Caller must not free the returned token. This
- * function is not async-signal-safe.
- */
-ProfileHandlerToken* ProfileHandlerRegisterCallback(
- ProfileHandlerCallback callback, void* callback_arg);
-
-/*
- * Unregisters a previously registered callback. Expects the token returned
- * by the corresponding ProfileHandlerRegisterCallback and asserts that the
- * passed token is valid. Unregistering the last callback disables the SIGPROF
- * signal handler. It waits for the currently running callback to
- * complete before returning. This function is not async-signal-safe.
- */
-void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token);
-
-/*
- * FOR TESTING ONLY
- * Unregisters all the callbacks, stops the timers (if shared) and disables the
- * SIGPROF handler. All the threads, including the main thread, need to be
- * re-registered after this call. This function is not async-signal-safe.
- */
-void ProfileHandlerReset();
-
-/*
- * Stores profile handler's current state. This function is not
- * async-signal-safe.
- */
-struct ProfileHandlerState {
- int32 frequency; /* Profiling frequency */
- int32 callback_count; /* Number of callbacks registered */
- int64 interrupts; /* Number of interrupts received */
- bool allowed; /* Profiling is allowed */
-};
-void ProfileHandlerGetState(struct ProfileHandlerState* state);
-
-#endif /* BASE_PROFILE_HANDLER_H_ */
diff --git a/src/third_party/gperftools-2.5/src/profiledata.cc b/src/third_party/gperftools-2.5/src/profiledata.cc
deleted file mode 100644
index 8b05d3aa45c..00000000000
--- a/src/third_party/gperftools-2.5/src/profiledata.cc
+++ /dev/null
@@ -1,332 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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
-// Chris Demetriou (refactoring)
-//
-// Collect profiling data.
-
-#include <config.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/time.h>
-#include <string.h>
-#include <fcntl.h>
-
-#include "profiledata.h"
-
-#include "base/logging.h"
-#include "base/sysinfo.h"
-
-// All of these are initialized in profiledata.h.
-const int ProfileData::kMaxStackDepth;
-const int ProfileData::kAssociativity;
-const int ProfileData::kBuckets;
-const int ProfileData::kBufferLength;
-
-ProfileData::Options::Options()
- : frequency_(1) {
-}
-
-// This function is safe to call from asynchronous signals (but is not
-// re-entrant). However, that's not part of its public interface.
-void ProfileData::Evict(const Entry& entry) {
- const int d = entry.depth;
- const int nslots = d + 2; // Number of slots needed in eviction buffer
- if (num_evicted_ + nslots > kBufferLength) {
- FlushEvicted();
- assert(num_evicted_ == 0);
- assert(nslots <= kBufferLength);
- }
- evict_[num_evicted_++] = entry.count;
- evict_[num_evicted_++] = d;
- memcpy(&evict_[num_evicted_], entry.stack, d * sizeof(Slot));
- num_evicted_ += d;
-}
-
-ProfileData::ProfileData()
- : hash_(0),
- evict_(0),
- num_evicted_(0),
- out_(-1),
- count_(0),
- evictions_(0),
- total_bytes_(0),
- fname_(0),
- start_time_(0) {
-}
-
-bool ProfileData::Start(const char* fname,
- const ProfileData::Options& options) {
- if (enabled()) {
- return false;
- }
-
- // Open output file and initialize various data structures
- int fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0666);
- if (fd < 0) {
- // Can't open outfile for write
- return false;
- }
-
- start_time_ = time(NULL);
- fname_ = strdup(fname);
-
- // Reset counters
- num_evicted_ = 0;
- count_ = 0;
- evictions_ = 0;
- total_bytes_ = 0;
-
- hash_ = new Bucket[kBuckets];
- evict_ = new Slot[kBufferLength];
- memset(hash_, 0, sizeof(hash_[0]) * kBuckets);
-
- // Record special entries
- evict_[num_evicted_++] = 0; // count for header
- evict_[num_evicted_++] = 3; // depth for header
- evict_[num_evicted_++] = 0; // Version number
- CHECK_NE(0, options.frequency());
- int period = 1000000 / options.frequency();
- evict_[num_evicted_++] = period; // Period (microseconds)
- evict_[num_evicted_++] = 0; // Padding
-
- out_ = fd;
-
- return true;
-}
-
-ProfileData::~ProfileData() {
- Stop();
-}
-
-// Dump /proc/maps data to fd. Copied from heap-profile-table.cc.
-#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR)
-
-static void FDWrite(int fd, const char* buf, size_t len) {
- while (len > 0) {
- ssize_t r;
- NO_INTR(r = write(fd, buf, len));
- RAW_CHECK(r >= 0, "write failed");
- buf += r;
- len -= r;
- }
-}
-
-static void DumpProcSelfMaps(int fd) {
- ProcMapsIterator::Buffer iterbuf;
- ProcMapsIterator it(0, &iterbuf); // 0 means "current pid"
-
- uint64 start, end, offset;
- int64 inode;
- char *flags, *filename;
- ProcMapsIterator::Buffer linebuf;
- while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) {
- int written = it.FormatLine(linebuf.buf_, sizeof(linebuf.buf_),
- start, end, flags, offset, inode, filename,
- 0);
- FDWrite(fd, linebuf.buf_, written);
- }
-}
-
-void ProfileData::Stop() {
- if (!enabled()) {
- return;
- }
-
- // Move data from hash table to eviction buffer
- for (int b = 0; b < kBuckets; b++) {
- Bucket* bucket = &hash_[b];
- for (int a = 0; a < kAssociativity; a++) {
- if (bucket->entry[a].count > 0) {
- Evict(bucket->entry[a]);
- }
- }
- }
-
- if (num_evicted_ + 3 > kBufferLength) {
- // Ensure there is enough room for end of data marker
- FlushEvicted();
- }
-
- // Write end of data marker
- evict_[num_evicted_++] = 0; // count
- evict_[num_evicted_++] = 1; // depth
- evict_[num_evicted_++] = 0; // end of data marker
- FlushEvicted();
-
- // Dump "/proc/self/maps" so we get list of mapped shared libraries
- DumpProcSelfMaps(out_);
-
- Reset();
- fprintf(stderr, "PROFILE: interrupts/evictions/bytes = %d/%d/%" PRIuS "\n",
- count_, evictions_, total_bytes_);
-}
-
-void ProfileData::Reset() {
- if (!enabled()) {
- return;
- }
-
- // Don't reset count_, evictions_, or total_bytes_ here. They're used
- // by Stop to print information about the profile after reset, and are
- // cleared by Start when starting a new profile.
- close(out_);
- delete[] hash_;
- hash_ = 0;
- delete[] evict_;
- evict_ = 0;
- num_evicted_ = 0;
- free(fname_);
- fname_ = 0;
- start_time_ = 0;
-
- out_ = -1;
-}
-
-// This function is safe to call from asynchronous signals (but is not
-// re-entrant). However, that's not part of its public interface.
-void ProfileData::GetCurrentState(State* state) const {
- if (enabled()) {
- state->enabled = true;
- state->start_time = start_time_;
- state->samples_gathered = count_;
- int buf_size = sizeof(state->profile_name);
- strncpy(state->profile_name, fname_, buf_size);
- state->profile_name[buf_size-1] = '\0';
- } else {
- state->enabled = false;
- state->start_time = 0;
- state->samples_gathered = 0;
- state->profile_name[0] = '\0';
- }
-}
-
-// This function is safe to call from asynchronous signals (but is not
-// re-entrant). However, that's not part of its public interface.
-void ProfileData::FlushTable() {
- if (!enabled()) {
- return;
- }
-
- // Move data from hash table to eviction buffer
- for (int b = 0; b < kBuckets; b++) {
- Bucket* bucket = &hash_[b];
- for (int a = 0; a < kAssociativity; a++) {
- if (bucket->entry[a].count > 0) {
- Evict(bucket->entry[a]);
- bucket->entry[a].depth = 0;
- bucket->entry[a].count = 0;
- }
- }
- }
-
- // Write out all pending data
- FlushEvicted();
-}
-
-void ProfileData::Add(int depth, const void* const* stack) {
- if (!enabled()) {
- return;
- }
-
- if (depth > kMaxStackDepth) depth = kMaxStackDepth;
- RAW_CHECK(depth > 0, "ProfileData::Add depth <= 0");
-
- // Make hash-value
- Slot h = 0;
- for (int i = 0; i < depth; i++) {
- Slot slot = reinterpret_cast<Slot>(stack[i]);
- h = (h << 8) | (h >> (8*(sizeof(h)-1)));
- h += (slot * 31) + (slot * 7) + (slot * 3);
- }
-
- count_++;
-
- // See if table already has an entry for this trace
- bool done = false;
- Bucket* bucket = &hash_[h % kBuckets];
- for (int a = 0; a < kAssociativity; a++) {
- Entry* e = &bucket->entry[a];
- if (e->depth == depth) {
- bool match = true;
- for (int i = 0; i < depth; i++) {
- if (e->stack[i] != reinterpret_cast<Slot>(stack[i])) {
- match = false;
- break;
- }
- }
- if (match) {
- e->count++;
- done = true;
- break;
- }
- }
- }
-
- if (!done) {
- // Evict entry with smallest count
- Entry* e = &bucket->entry[0];
- for (int a = 1; a < kAssociativity; a++) {
- if (bucket->entry[a].count < e->count) {
- e = &bucket->entry[a];
- }
- }
- if (e->count > 0) {
- evictions_++;
- Evict(*e);
- }
-
- // Use the newly evicted entry
- e->depth = depth;
- e->count = 1;
- for (int i = 0; i < depth; i++) {
- e->stack[i] = reinterpret_cast<Slot>(stack[i]);
- }
- }
-}
-
-// This function is safe to call from asynchronous signals (but is not
-// re-entrant). However, that's not part of its public interface.
-void ProfileData::FlushEvicted() {
- if (num_evicted_ > 0) {
- const char* buf = reinterpret_cast<char*>(evict_);
- size_t bytes = sizeof(evict_[0]) * num_evicted_;
- total_bytes_ += bytes;
- FDWrite(out_, buf, bytes);
- }
- num_evicted_ = 0;
-}
diff --git a/src/third_party/gperftools-2.5/src/profiledata.h b/src/third_party/gperftools-2.5/src/profiledata.h
deleted file mode 100644
index 44033f02d76..00000000000
--- a/src/third_party/gperftools-2.5/src/profiledata.h
+++ /dev/null
@@ -1,184 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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
-// Chris Demetriou (refactoring)
-//
-// Collect profiling data.
-//
-// The profile data file format is documented in
-// doc/cpuprofile-fileformat.html
-
-
-#ifndef BASE_PROFILEDATA_H_
-#define BASE_PROFILEDATA_H_
-
-#include <config.h>
-#include <time.h> // for time_t
-#include <stdint.h>
-#include "base/basictypes.h"
-
-// A class that accumulates profile samples and writes them to a file.
-//
-// Each sample contains a stack trace and a count. Memory usage is
-// reduced by combining profile samples that have the same stack trace
-// by adding up the associated counts.
-//
-// Profile data is accumulated in a bounded amount of memory, and will
-// flushed to a file as necessary to stay within the memory limit.
-//
-// Use of this class assumes external synchronization. The exact
-// requirements of that synchronization are that:
-//
-// - 'Add' may be called from asynchronous signals, but is not
-// re-entrant.
-//
-// - None of 'Start', 'Stop', 'Reset', 'Flush', and 'Add' may be
-// called at the same time.
-//
-// - 'Start', 'Stop', or 'Reset' should not be called while 'Enabled'
-// or 'GetCurrent' are running, and vice versa.
-//
-// A profiler which uses asyncronous signals to add samples will
-// typically use two locks to protect this data structure:
-//
-// - A SpinLock which is held over all calls except for the 'Add'
-// call made from the signal handler.
-//
-// - A SpinLock which is held over calls to 'Start', 'Stop', 'Reset',
-// 'Flush', and 'Add'. (This SpinLock should be acquired after
-// the first SpinLock in all cases where both are needed.)
-class ProfileData {
- public:
- struct State {
- bool enabled; // Is profiling currently enabled?
- time_t start_time; // If enabled, when was profiling started?
- char profile_name[1024]; // Name of file being written, or '\0'
- int samples_gathered; // Number of samples gathered to far (or 0)
- };
-
- class Options {
- public:
- Options();
-
- // Get and set the sample frequency.
- int frequency() const {
- return frequency_;
- }
- void set_frequency(int frequency) {
- frequency_ = frequency;
- }
-
- private:
- int frequency_; // Sample frequency.
- };
-
- static const int kMaxStackDepth = 64; // Max stack depth stored in profile
-
- ProfileData();
- ~ProfileData();
-
- // If data collection is not already enabled start to collect data
- // into fname. Parameters related to this profiling run are specified
- // by 'options'.
- //
- // Returns true if data collection could be started, otherwise (if an
- // error occurred or if data collection was already enabled) returns
- // false.
- bool Start(const char *fname, const Options& options);
-
- // If data collection is enabled, stop data collection and write the
- // data to disk.
- void Stop();
-
- // Stop data collection without writing anything else to disk, and
- // discard any collected data.
- void Reset();
-
- // If data collection is enabled, record a sample with 'depth'
- // entries from 'stack'. (depth must be > 0.) At most
- // kMaxStackDepth stack entries will be recorded, starting with
- // stack[0].
- //
- // This function is safe to call from asynchronous signals (but is
- // not re-entrant).
- void Add(int depth, const void* const* stack);
-
- // If data collection is enabled, write the data to disk (and leave
- // the collector enabled).
- void FlushTable();
-
- // Is data collection currently enabled?
- bool enabled() const { return out_ >= 0; }
-
- // Get the current state of the data collector.
- void GetCurrentState(State* state) const;
-
- private:
- static const int kAssociativity = 4; // For hashtable
- static const int kBuckets = 1 << 10; // For hashtable
- static const int kBufferLength = 1 << 18; // For eviction buffer
-
- // Type of slots: each slot can be either a count, or a PC value
- typedef uintptr_t Slot;
-
- // Hash-table/eviction-buffer entry (a.k.a. a sample)
- struct Entry {
- Slot count; // Number of hits
- Slot depth; // Stack depth
- Slot stack[kMaxStackDepth]; // Stack contents
- };
-
- // Hash table bucket
- struct Bucket {
- Entry entry[kAssociativity];
- };
-
- Bucket* hash_; // hash table
- Slot* evict_; // evicted entries
- int num_evicted_; // how many evicted entries?
- int out_; // fd for output file.
- int count_; // How many samples recorded
- int evictions_; // How many evictions
- size_t total_bytes_; // How much output
- char* fname_; // Profile file name
- time_t start_time_; // Start time, or 0
-
- // Move 'entry' to the eviction buffer.
- void Evict(const Entry& entry);
-
- // Write contents of eviction buffer to disk.
- void FlushEvicted();
-
- DISALLOW_COPY_AND_ASSIGN(ProfileData);
-};
-
-#endif // BASE_PROFILEDATA_H_
diff --git a/src/third_party/gperftools-2.5/src/profiler.cc b/src/third_party/gperftools-2.5/src/profiler.cc
deleted file mode 100644
index f4f59900088..00000000000
--- a/src/third_party/gperftools-2.5/src/profiler.cc
+++ /dev/null
@@ -1,431 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-// Chris Demetriou (refactoring)
-//
-// Profile current program by sampling stack-trace every so often
-
-#include "config.h"
-#include "getpc.h" // should be first to get the _GNU_SOURCE dfn
-#include <signal.h>
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for getpid()
-#endif
-#if defined(HAVE_SYS_UCONTEXT_H)
-#include <sys/ucontext.h>
-#elif defined(HAVE_UCONTEXT_H)
-#include <ucontext.h>
-#elif defined(HAVE_CYGWIN_SIGNAL_H)
-#include <cygwin/signal.h>
-typedef ucontext ucontext_t;
-#else
-typedef int ucontext_t; // just to quiet the compiler, mostly
-#endif
-#include <sys/time.h>
-#include <string>
-#include <gperftools/profiler.h>
-#include <gperftools/stacktrace.h>
-#include "base/commandlineflags.h"
-#include "base/logging.h"
-#include "base/googleinit.h"
-#include "base/spinlock.h"
-#include "base/sysinfo.h" /* for GetUniquePathFromEnv, etc */
-#include "profiledata.h"
-#include "profile-handler.h"
-#ifdef HAVE_CONFLICT_SIGNAL_H
-#include "conflict-signal.h" /* used on msvc machines */
-#endif
-
-using std::string;
-
-DEFINE_bool(cpu_profiler_unittest,
- EnvToBool("PERFTOOLS_UNITTEST", true),
- "Determines whether or not we are running under the \
- control of a unit test. This allows us to include or \
- exclude certain behaviours.");
-
-// Collects up all profile data. This is a singleton, which is
-// initialized by a constructor at startup. If no cpu profiler
-// signal is specified then the profiler lifecycle is either
-// manaully controlled via the API or attached to the scope of
-// the singleton (program scope). Otherwise the cpu toggle is
-// used to allow for user selectable control via signal generation.
-// This is very useful for profiling a daemon process without
-// having to start and stop the daemon or having to modify the
-// source code to use the cpu profiler API.
-class CpuProfiler {
- public:
- CpuProfiler();
- ~CpuProfiler();
-
- // Start profiler to write profile info into fname
- bool Start(const char* fname, const ProfilerOptions* options);
-
- // Stop profiling and write the data to disk.
- void Stop();
-
- // Write the data to disk (and continue profiling).
- void FlushTable();
-
- bool Enabled();
-
- void GetCurrentState(ProfilerState* state);
-
- static CpuProfiler instance_;
-
- private:
- // This lock implements the locking requirements described in the ProfileData
- // documentation, specifically:
- //
- // lock_ is held all over all collector_ method calls except for the 'Add'
- // call made from the signal handler, to protect against concurrent use of
- // collector_'s control routines. Code other than signal handler must
- // unregister the signal handler before calling any collector_ method.
- // 'Add' method in the collector is protected by a guarantee from
- // ProfileHandle that only one instance of prof_handler can run at a time.
- SpinLock lock_;
- ProfileData collector_;
-
- // Filter function and its argument, if any. (NULL means include all
- // samples). Set at start, read-only while running. Written while holding
- // lock_, read and executed in the context of SIGPROF interrupt.
- int (*filter_)(void*);
- void* filter_arg_;
-
- // Opaque token returned by the profile handler. To be used when calling
- // ProfileHandlerUnregisterCallback.
- ProfileHandlerToken* prof_handler_token_;
-
- // Sets up a callback to receive SIGPROF interrupt.
- void EnableHandler();
-
- // Disables receiving SIGPROF interrupt.
- void DisableHandler();
-
- // Signal handler that records the interrupted pc in the profile data.
- static void prof_handler(int sig, siginfo_t*, void* signal_ucontext,
- void* cpu_profiler);
-};
-
-// Signal handler that is registered when a user selectable signal
-// number is defined in the environment variable CPUPROFILESIGNAL.
-static void CpuProfilerSwitch(int signal_number)
-{
- bool static started = false;
- static unsigned profile_count = 0;
- static char base_profile_name[1024] = "\0";
-
- if (base_profile_name[0] == '\0') {
- if (!GetUniquePathFromEnv("CPUPROFILE", base_profile_name)) {
- RAW_LOG(FATAL,"Cpu profiler switch is registered but no CPUPROFILE is defined");
- return;
- }
- }
- if (!started)
- {
- char full_profile_name[1024];
-
- snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u",
- base_profile_name, profile_count++);
-
- if(!ProfilerStart(full_profile_name))
- {
- RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n",
- full_profile_name, strerror(errno));
- }
- }
- else
- {
- ProfilerStop();
- }
- started = !started;
-}
-
-// Profile data structure singleton: Constructor will check to see if
-// profiling should be enabled. Destructor will write profile data
-// out to disk.
-CpuProfiler CpuProfiler::instance_;
-
-// Initialize profiling: activated if getenv("CPUPROFILE") exists.
-CpuProfiler::CpuProfiler()
- : prof_handler_token_(NULL) {
- // TODO(cgd) Move this code *out* of the CpuProfile constructor into a
- // separate object responsible for initialization. With ProfileHandler there
- // is no need to limit the number of profilers.
- if (getenv("CPUPROFILE") == NULL) {
- if (!FLAGS_cpu_profiler_unittest) {
- RAW_LOG(WARNING, "CPU profiler linked but no valid CPUPROFILE environment variable found\n");
- }
- return;
- }
-
- // We don't enable profiling if setuid -- it's a security risk
-#ifdef HAVE_GETEUID
- if (getuid() != geteuid()) {
- if (!FLAGS_cpu_profiler_unittest) {
- RAW_LOG(WARNING, "Cannot perform CPU profiling when running with setuid\n");
- }
- return;
- }
-#endif
-
- char *signal_number_str = getenv("CPUPROFILESIGNAL");
- if (signal_number_str != NULL) {
- long int signal_number = strtol(signal_number_str, NULL, 10);
- if (signal_number >= 1 && signal_number <= 64) {
- intptr_t old_signal_handler = reinterpret_cast<intptr_t>(signal(signal_number, CpuProfilerSwitch));
- if (old_signal_handler == 0) {
- RAW_LOG(INFO,"Using signal %d as cpu profiling switch", signal_number);
- } else {
- RAW_LOG(FATAL, "Signal %d already in use\n", signal_number);
- }
- } else {
- RAW_LOG(FATAL, "Signal number %s is invalid\n", signal_number_str);
- }
- } else {
- char fname[PATH_MAX];
- if (!GetUniquePathFromEnv("CPUPROFILE", fname)) {
- if (!FLAGS_cpu_profiler_unittest) {
- RAW_LOG(WARNING, "CPU profiler linked but no valid CPUPROFILE environment variable found\n");
- }
- return;
- }
-
- if (!Start(fname, NULL)) {
- RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n",
- fname, strerror(errno));
- }
- }
-}
-
-bool CpuProfiler::Start(const char* fname, const ProfilerOptions* options) {
- SpinLockHolder cl(&lock_);
-
- if (collector_.enabled()) {
- return false;
- }
-
- ProfileHandlerState prof_handler_state;
- ProfileHandlerGetState(&prof_handler_state);
-
- ProfileData::Options collector_options;
- collector_options.set_frequency(prof_handler_state.frequency);
- if (!collector_.Start(fname, collector_options)) {
- return false;
- }
-
- filter_ = NULL;
- if (options != NULL && options->filter_in_thread != NULL) {
- filter_ = options->filter_in_thread;
- filter_arg_ = options->filter_in_thread_arg;
- }
-
- // Setup handler for SIGPROF interrupts
- EnableHandler();
-
- return true;
-}
-
-CpuProfiler::~CpuProfiler() {
- Stop();
-}
-
-// Stop profiling and write out any collected profile data
-void CpuProfiler::Stop() {
- SpinLockHolder cl(&lock_);
-
- if (!collector_.enabled()) {
- return;
- }
-
- // Unregister prof_handler to stop receiving SIGPROF interrupts before
- // stopping the collector.
- DisableHandler();
-
- // DisableHandler waits for the currently running callback to complete and
- // guarantees no future invocations. It is safe to stop the collector.
- collector_.Stop();
-}
-
-void CpuProfiler::FlushTable() {
- SpinLockHolder cl(&lock_);
-
- if (!collector_.enabled()) {
- return;
- }
-
- // Unregister prof_handler to stop receiving SIGPROF interrupts before
- // flushing the profile data.
- DisableHandler();
-
- // DisableHandler waits for the currently running callback to complete and
- // guarantees no future invocations. It is safe to flush the profile data.
- collector_.FlushTable();
-
- EnableHandler();
-}
-
-bool CpuProfiler::Enabled() {
- SpinLockHolder cl(&lock_);
- return collector_.enabled();
-}
-
-void CpuProfiler::GetCurrentState(ProfilerState* state) {
- ProfileData::State collector_state;
- {
- SpinLockHolder cl(&lock_);
- collector_.GetCurrentState(&collector_state);
- }
-
- state->enabled = collector_state.enabled;
- state->start_time = static_cast<time_t>(collector_state.start_time);
- state->samples_gathered = collector_state.samples_gathered;
- int buf_size = sizeof(state->profile_name);
- strncpy(state->profile_name, collector_state.profile_name, buf_size);
- state->profile_name[buf_size-1] = '\0';
-}
-
-void CpuProfiler::EnableHandler() {
- RAW_CHECK(prof_handler_token_ == NULL, "SIGPROF handler already registered");
- prof_handler_token_ = ProfileHandlerRegisterCallback(prof_handler, this);
- RAW_CHECK(prof_handler_token_ != NULL, "Failed to set up SIGPROF handler");
-}
-
-void CpuProfiler::DisableHandler() {
- RAW_CHECK(prof_handler_token_ != NULL, "SIGPROF handler is not registered");
- ProfileHandlerUnregisterCallback(prof_handler_token_);
- prof_handler_token_ = NULL;
-}
-
-// Signal handler that records the pc in the profile-data structure. We do no
-// synchronization here. profile-handler.cc guarantees that at most one
-// instance of prof_handler() will run at a time. All other routines that
-// access the data touched by prof_handler() disable this signal handler before
-// accessing the data and therefore cannot execute concurrently with
-// prof_handler().
-void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext,
- void* cpu_profiler) {
- CpuProfiler* instance = static_cast<CpuProfiler*>(cpu_profiler);
-
- if (instance->filter_ == NULL ||
- (*instance->filter_)(instance->filter_arg_)) {
- void* stack[ProfileData::kMaxStackDepth];
-
- // Under frame-pointer-based unwinding at least on x86, the
- // top-most active routine doesn't show up as a normal frame, but
- // as the "pc" value in the signal handler context.
- stack[0] = GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext));
-
- // We skip the top three stack trace entries (this function,
- // SignalHandler::SignalHandler and one signal handler frame)
- // since they are artifacts of profiling and should not be
- // measured. Other profiling related frames may be removed by
- // "pprof" at analysis time. Instead of skipping the top frames,
- // we could skip nothing, but that would increase the profile size
- // unnecessarily.
- int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1,
- 3, signal_ucontext);
-
- void **used_stack;
- if (depth > 0 && stack[1] == stack[0]) {
- // in case of non-frame-pointer-based unwinding we will get
- // duplicate of PC in stack[1], which we don't want
- used_stack = stack + 1;
- } else {
- used_stack = stack;
- depth++; // To account for pc value in stack[0];
- }
-
- instance->collector_.Add(depth, used_stack);
- }
-}
-
-#if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
-
-extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() {
- ProfileHandlerRegisterThread();
-}
-
-extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() {
- CpuProfiler::instance_.FlushTable();
-}
-
-extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() {
- return CpuProfiler::instance_.Enabled();
-}
-
-extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname) {
- return CpuProfiler::instance_.Start(fname, NULL);
-}
-
-extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions(
- const char *fname, const ProfilerOptions *options) {
- return CpuProfiler::instance_.Start(fname, options);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() {
- CpuProfiler::instance_.Stop();
-}
-
-extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(
- ProfilerState* state) {
- CpuProfiler::instance_.GetCurrentState(state);
-}
-
-#else // OS_CYGWIN
-
-// 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.
-extern "C" void ProfilerRegisterThread() { }
-extern "C" void ProfilerFlush() { }
-extern "C" int ProfilingIsEnabledForAllThreads() { return 0; }
-extern "C" int ProfilerStart(const char* fname) { return 0; }
-extern "C" int ProfilerStartWithOptions(const char *fname,
- const ProfilerOptions *options) {
- return 0;
-}
-extern "C" void ProfilerStop() { }
-extern "C" void ProfilerGetCurrentState(ProfilerState* state) {
- memset(state, 0, sizeof(*state));
-}
-
-#endif // OS_CYGWIN
-
-// DEPRECATED routines
-extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { }
-extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { }
diff --git a/src/third_party/gperftools-2.5/src/raw_printer.cc b/src/third_party/gperftools-2.5/src/raw_printer.cc
deleted file mode 100644
index 3cf028eeae0..00000000000
--- a/src/third_party/gperftools-2.5/src/raw_printer.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: sanjay@google.com (Sanjay Ghemawat)
-
-#include <config.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include "raw_printer.h"
-#include "base/logging.h"
-
-namespace base {
-
-RawPrinter::RawPrinter(char* buf, int length)
- : base_(buf),
- ptr_(buf),
- limit_(buf + length - 1) {
- RAW_DCHECK(length > 0, "");
- *ptr_ = '\0';
- *limit_ = '\0';
-}
-
-void RawPrinter::Printf(const char* format, ...) {
- if (limit_ > ptr_) {
- va_list ap;
- va_start(ap, format);
- int avail = limit_ - ptr_;
- // We pass avail+1 to vsnprintf() since that routine needs room
- // to store the trailing \0.
- const int r = perftools_vsnprintf(ptr_, avail+1, format, ap);
- va_end(ap);
- if (r < 0) {
- // Perhaps an old glibc that returns -1 on truncation?
- ptr_ = limit_;
- } else if (r > avail) {
- // Truncation
- ptr_ = limit_;
- } else {
- ptr_ += r;
- }
- }
-}
-
-}
diff --git a/src/third_party/gperftools-2.5/src/raw_printer.h b/src/third_party/gperftools-2.5/src/raw_printer.h
deleted file mode 100644
index 9288bb5eeaa..00000000000
--- a/src/third_party/gperftools-2.5/src/raw_printer.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat
-//
-// A printf() wrapper that writes into a fixed length buffer.
-// Useful in low-level code that does not want to use allocating
-// routines like StringPrintf().
-//
-// The implementation currently uses vsnprintf(). This seems to
-// be fine for use in many low-level contexts, but we may need to
-// rethink this decision if we hit a problem with it calling
-// down into malloc() etc.
-
-#ifndef BASE_RAW_PRINTER_H_
-#define BASE_RAW_PRINTER_H_
-
-#include <config.h>
-#include "base/basictypes.h"
-
-namespace base {
-
-class RawPrinter {
- public:
- // REQUIRES: "length > 0"
- // Will printf any data added to this into "buf[0,length-1]" and
- // will arrange to always keep buf[] null-terminated.
- RawPrinter(char* buf, int length);
-
- // Return the number of bytes that have been appended to the string
- // so far. Does not count any bytes that were dropped due to overflow.
- int length() const { return (ptr_ - base_); }
-
- // Return the number of bytes that can be added to this.
- int space_left() const { return (limit_ - ptr_); }
-
- // Format the supplied arguments according to the "format" string
- // and append to this. Will silently truncate the output if it does
- // not fit.
- void Printf(const char* format, ...)
-#ifdef HAVE___ATTRIBUTE__
- __attribute__ ((__format__ (__printf__, 2, 3)))
-#endif
-;
-
- private:
- // We can write into [ptr_ .. limit_-1].
- // *limit_ is also writable, but reserved for a terminating \0
- // in case we overflow.
- //
- // Invariants: *ptr_ == \0
- // Invariants: *limit_ == \0
- char* base_; // Initial pointer
- char* ptr_; // Where should we write next
- char* limit_; // One past last non-\0 char we can write
-
- DISALLOW_COPY_AND_ASSIGN(RawPrinter);
-};
-
-}
-
-#endif // BASE_RAW_PRINTER_H_
diff --git a/src/third_party/gperftools-2.5/src/sampler.cc b/src/third_party/gperftools-2.5/src/sampler.cc
deleted file mode 100755
index cc711123340..00000000000
--- a/src/third_party/gperftools-2.5/src/sampler.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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.
-
-// ---
-// All Rights Reserved.
-//
-// Author: Daniel Ford
-
-#include "sampler.h"
-
-#include <algorithm> // For min()
-#include <math.h>
-#include "base/commandlineflags.h"
-
-using std::min;
-
-// The approximate gap in bytes between sampling actions.
-// I.e., we take one sample approximately once every
-// tcmalloc_sample_parameter bytes of allocation
-// i.e. about once every 512KB if value is 1<<19.
-#ifdef NO_TCMALLOC_SAMPLES
-DEFINE_int64(tcmalloc_sample_parameter, 0,
- "Unused: code is compiled with NO_TCMALLOC_SAMPLES");
-#else
-DEFINE_int64(tcmalloc_sample_parameter,
- EnvToInt64("TCMALLOC_SAMPLE_PARAMETER", 0),
- "The approximate gap in bytes between sampling actions. "
- "This must be between 1 and 2^58.");
-#endif
-
-namespace tcmalloc {
-
-// Statics for Sampler
-double Sampler::log_table_[1<<kFastlogNumBits];
-
-// Populate the lookup table for FastLog2.
-// This approximates the log2 curve with a step function.
-// Steps have height equal to log2 of the mid-point of the step.
-void Sampler::PopulateFastLog2Table() {
- for (int i = 0; i < (1<<kFastlogNumBits); i++) {
- log_table_[i] = (log(1.0 + static_cast<double>(i+0.5)/(1<<kFastlogNumBits))
- / log(2.0));
- }
-}
-
-int Sampler::GetSamplePeriod() {
- return FLAGS_tcmalloc_sample_parameter;
-}
-
-// Run this before using your sampler
-void Sampler::Init(uint32_t seed) {
- // Initialize PRNG
- if (seed != 0) {
- rnd_ = seed;
- } else {
- rnd_ = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this));
- if (rnd_ == 0) {
- rnd_ = 1;
- }
- }
- // Step it forward 20 times for good measure
- for (int i = 0; i < 20; i++) {
- rnd_ = NextRandom(rnd_);
- }
- // Initialize counter
- bytes_until_sample_ = PickNextSamplingPoint();
-}
-
-// Initialize the Statics for the Sampler class
-void Sampler::InitStatics() {
- PopulateFastLog2Table();
-}
-
-// Generates a geometric variable with the specified mean (512K by default).
-// This is done by generating a random number between 0 and 1 and applying
-// the inverse cumulative distribution function for an exponential.
-// Specifically: Let m be the inverse of the sample period, then
-// the probability distribution function is m*exp(-mx) so the CDF is
-// p = 1 - exp(-mx), so
-// q = 1 - p = exp(-mx)
-// log_e(q) = -mx
-// -log_e(q)/m = x
-// log_2(q) * (-log_e(2) * 1/m) = x
-// In the code, q is actually in the range 1 to 2**26, hence the -26 below
-size_t Sampler::PickNextSamplingPoint() {
- rnd_ = NextRandom(rnd_);
- // Take the top 26 bits as the random number
- // (This plus the 1<<58 sampling bound give a max possible step of
- // 5194297183973780480 bytes.)
- const uint64_t prng_mod_power = 48; // Number of bits in prng
- // The uint32_t cast is to prevent a (hard-to-reproduce) NAN
- // under piii debug for some binaries.
- double q = static_cast<uint32_t>(rnd_ >> (prng_mod_power - 26)) + 1.0;
- // Put the computed p-value through the CDF of a geometric.
- // For faster performance (save ~1/20th exec time), replace
- // min(0.0, FastLog2(q) - 26) by (Fastlog2(q) - 26.000705)
- // The value 26.000705 is used rather than 26 to compensate
- // for inaccuracies in FastLog2 which otherwise result in a
- // negative answer.
- return static_cast<size_t>(min(0.0, (FastLog2(q) - 26)) * (-log(2.0)
- * FLAGS_tcmalloc_sample_parameter) + 1);
-}
-
-} // namespace tcmalloc
diff --git a/src/third_party/gperftools-2.5/src/sampler.h b/src/third_party/gperftools-2.5/src/sampler.h
deleted file mode 100755
index eb316d7493d..00000000000
--- a/src/third_party/gperftools-2.5/src/sampler.h
+++ /dev/null
@@ -1,180 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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.
-
-// ---
-// All Rights Reserved.
-//
-// Author: Daniel Ford
-
-#ifndef TCMALLOC_SAMPLER_H_
-#define TCMALLOC_SAMPLER_H_
-
-#include "config.h"
-#include <stddef.h> // for size_t
-#ifdef HAVE_STDINT_H
-#include <stdint.h> // for uint64_t, uint32_t, int32_t
-#endif
-#include <string.h> // for memcpy
-#include "base/basictypes.h" // for ASSERT
-#include "internal_logging.h" // for ASSERT
-
-namespace tcmalloc {
-
-//-------------------------------------------------------------------
-// Sampler to decide when to create a sample trace for an allocation
-// Not thread safe: Each thread should have it's own sampler object.
-// Caller must use external synchronization if used
-// from multiple threads.
-//
-// With 512K average sample step (the default):
-// the probability of sampling a 4K allocation is about 0.00778
-// the probability of sampling a 1MB allocation is about 0.865
-// the probability of sampling a 1GB allocation is about 1.00000
-// In general, the probablity of sampling is an allocation of size X
-// given a flag value of Y (default 1M) is:
-// 1 - e^(-X/Y)
-//
-// With 128K average sample step:
-// the probability of sampling a 1MB allocation is about 0.99966
-// the probability of sampling a 1GB allocation is about 1.0
-// (about 1 - 2**(-26))
-// With 1M average sample step:
-// the probability of sampling a 4K allocation is about 0.00390
-// the probability of sampling a 1MB allocation is about 0.632
-// the probability of sampling a 1GB allocation is about 1.0
-//
-// The sampler works by representing memory as a long stream from
-// which allocations are taken. Some of the bytes in this stream are
-// marked and if an allocation includes a marked byte then it is
-// sampled. Bytes are marked according to a Poisson point process
-// with each byte being marked independently with probability
-// p = 1/tcmalloc_sample_parameter. This makes the probability
-// of sampling an allocation of X bytes equal to the CDF of
-// a geometric with mean tcmalloc_sample_parameter. (ie. the
-// probability that at least one byte in the range is marked). This
-// is accurately given by the CDF of the corresponding exponential
-// distribution : 1 - e^(X/tcmalloc_sample_parameter_)
-// Independence of the byte marking ensures independence of
-// the sampling of each allocation.
-//
-// This scheme is implemented by noting that, starting from any
-// fixed place, the number of bytes until the next marked byte
-// is geometrically distributed. This number is recorded as
-// bytes_until_sample_. Every allocation subtracts from this
-// number until it is less than 0. When this happens the current
-// allocation is sampled.
-//
-// When an allocation occurs, bytes_until_sample_ is reset to
-// a new independtly sampled geometric number of bytes. The
-// memoryless property of the point process means that this may
-// be taken as the number of bytes after the end of the current
-// allocation until the next marked byte. This ensures that
-// very large allocations which would intersect many marked bytes
-// only result in a single call to PickNextSamplingPoint.
-//-------------------------------------------------------------------
-
-class PERFTOOLS_DLL_DECL Sampler {
- public:
- // Initialize this sampler.
- // Passing a seed of 0 gives a non-deterministic
- // seed value given by casting the object ("this")
- void Init(uint32_t seed);
- void Cleanup();
-
- // Record allocation of "k" bytes. Return true iff allocation
- // should be sampled
- bool SampleAllocation(size_t k);
-
- // Generate a geometric with mean 512K (or FLAG_tcmalloc_sample_parameter)
- size_t PickNextSamplingPoint();
-
- // Initialize the statics for the Sampler class
- static void InitStatics();
-
- // Returns the current sample period
- int GetSamplePeriod();
-
- // The following are public for the purposes of testing
- static uint64_t NextRandom(uint64_t rnd_); // Returns the next prng value
- static double FastLog2(const double & d); // Computes Log2(x) quickly
- static void PopulateFastLog2Table(); // Populate the lookup table
-
- private:
- size_t bytes_until_sample_; // Bytes until we sample next
- uint64_t rnd_; // Cheap random number generator
-
- // Statics for the fast log
- // Note that this code may not depend on anything in //util
- // hence the duplication of functionality here
- static const int kFastlogNumBits = 10;
- static const int kFastlogMask = (1 << kFastlogNumBits) - 1;
- static double log_table_[1<<kFastlogNumBits]; // Constant
-};
-
-inline bool Sampler::SampleAllocation(size_t k) {
- if (bytes_until_sample_ < k) {
- bytes_until_sample_ = PickNextSamplingPoint();
- return true;
- } else {
- bytes_until_sample_ -= k;
- return false;
- }
-}
-
-// Inline functions which are public for testing purposes
-
-// Returns the next prng value.
-// pRNG is: aX+b mod c with a = 0x5DEECE66D, b = 0xB, c = 1<<48
-// This is the lrand64 generator.
-inline uint64_t Sampler::NextRandom(uint64_t rnd) {
- const uint64_t prng_mult = 0x5DEECE66DLL;
- const uint64_t prng_add = 0xB;
- const uint64_t prng_mod_power = 48;
- const uint64_t prng_mod_mask =
- ~((~static_cast<uint64_t>(0)) << prng_mod_power);
- return (prng_mult * rnd + prng_add) & prng_mod_mask;
-}
-
-// Adapted from //util/math/fastmath.[h|cc] by Noam Shazeer
-// This mimics the VeryFastLog2 code in those files
-inline double Sampler::FastLog2(const double & d) {
- ASSERT(d>0);
- COMPILE_ASSERT(sizeof(d) == sizeof(uint64_t), DoubleMustBe64Bits);
- uint64_t x;
- memcpy(&x, &d, sizeof(x)); // we depend on the compiler inlining this
- const uint32_t x_high = x >> 32;
- const uint32_t y = x_high >> (20 - kFastlogNumBits) & kFastlogMask;
- const int32_t exponent = ((x_high >> 20) & 0x7FF) - 1023;
- return exponent + log_table_[y];
-}
-
-} // namespace tcmalloc
-
-#endif // TCMALLOC_SAMPLER_H_
diff --git a/src/third_party/gperftools-2.5/src/solaris/libstdc++.la b/src/third_party/gperftools-2.5/src/solaris/libstdc++.la
deleted file mode 100644
index 3edf4254192..00000000000
--- a/src/third_party/gperftools-2.5/src/solaris/libstdc++.la
+++ /dev/null
@@ -1,51 +0,0 @@
-# libstdc++.la - a libtool library file
-# Generated by ltmain.sh - GNU libtool 1.4a-GCC3.0 (1.641.2.256 2001/05/28 20:09:07 with GCC-local changes)
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# ---
-# NOTE: This file lives in /usr/sfw/lib on Solaris 10. Unfortunately,
-# due to an apparent bug in the Solaris 10 6/06 release,
-# /usr/sfw/lib/libstdc++.la is empty. Below is the correct content,
-# according to
-# http://forum.java.sun.com/thread.jspa?threadID=5073150
-# By passing LDFLAGS='-Lsrc/solaris' to configure, make will pick up
-# this copy of the file rather than the empty copy in /usr/sfw/lib.
-#
-# Also see
-# http://www.technicalarticles.org/index.php/Compiling_MySQL_5.0_on_Solaris_10
-#
-# Note: this is for 32-bit systems. If you have a 64-bit system,
-# uncomment the appropriate dependency_libs line below.
-# ----
-
-# The name that we can dlopen(3).
-dlname='libstdc++.so.6'
-
-# Names of this library.
-library_names='libstdc++.so.6.0.3 libstdc++.so.6 libstdc++.so'
-
-# The name of the static archive.
-old_library='libstdc++.a'
-
-# Libraries that this one depends upon.
-# 32-bit version:
-dependency_libs='-lc -lm -L/usr/sfw/lib -lgcc_s'
-# 64-bit version:
-#dependency_libs='-L/lib/64 -lc -lm -L/usr/sfw/lib/64 -lgcc_s'
-
-# Version information for libstdc++.
-current=6
-age=0
-revision=3
-
-# Is this an already installed library?
-installed=yes
-
-# Files to dlopen/dlpreopen
-dlopen=''
-dlpreopen=''
-
-# Directory that this library needs to be installed in:
-libdir='/usr/sfw/lib'
diff --git a/src/third_party/gperftools-2.5/src/span.cc b/src/third_party/gperftools-2.5/src/span.cc
deleted file mode 100644
index 4d089640d18..00000000000
--- a/src/third_party/gperftools-2.5/src/span.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-
-#include <config.h>
-#include "span.h"
-
-#include <string.h> // for NULL, memset
-
-#include "internal_logging.h" // for ASSERT
-#include "page_heap_allocator.h" // for PageHeapAllocator
-#include "static_vars.h" // for Static
-
-namespace tcmalloc {
-
-#ifdef SPAN_HISTORY
-void Event(Span* span, char op, int v = 0) {
- span->history[span->nexthistory] = op;
- span->value[span->nexthistory] = v;
- span->nexthistory++;
- if (span->nexthistory == sizeof(span->history)) span->nexthistory = 0;
-}
-#endif
-
-Span* NewSpan(PageID p, Length len) {
- Span* result = Static::span_allocator()->New();
- memset(result, 0, sizeof(*result));
- result->start = p;
- result->length = len;
-#ifdef SPAN_HISTORY
- result->nexthistory = 0;
-#endif
- return result;
-}
-
-void DeleteSpan(Span* span) {
-#ifndef NDEBUG
- // In debug mode, trash the contents of deleted Spans
- memset(span, 0x3f, sizeof(*span));
-#endif
- Static::span_allocator()->Delete(span);
-}
-
-void DLL_Init(Span* list) {
- list->next = list;
- list->prev = list;
-}
-
-void DLL_Remove(Span* span) {
- span->prev->next = span->next;
- span->next->prev = span->prev;
- span->prev = NULL;
- span->next = NULL;
-}
-
-int DLL_Length(const Span* list) {
- int result = 0;
- for (Span* s = list->next; s != list; s = s->next) {
- result++;
- }
- return result;
-}
-
-void DLL_Prepend(Span* list, Span* span) {
- ASSERT(span->next == NULL);
- ASSERT(span->prev == NULL);
- span->next = list->next;
- span->prev = list;
- list->next->prev = span;
- list->next = span;
-}
-
-} // namespace tcmalloc
diff --git a/src/third_party/gperftools-2.5/src/span.h b/src/third_party/gperftools-2.5/src/span.h
deleted file mode 100644
index 83feda19c5e..00000000000
--- a/src/third_party/gperftools-2.5/src/span.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-//
-// A Span is a contiguous run of pages.
-
-#ifndef TCMALLOC_SPAN_H_
-#define TCMALLOC_SPAN_H_
-
-#include <config.h>
-#include "common.h"
-
-namespace tcmalloc {
-
-// Information kept for a span (a contiguous run of pages).
-struct Span {
- PageID start; // Starting page number
- Length length; // Number of pages in span
- Span* next; // Used when in link list
- Span* prev; // Used when in link list
- void* objects; // Linked list of free objects
- unsigned int refcount : 16; // Number of non-free objects
- unsigned int sizeclass : 8; // Size-class for small objects (or 0)
- unsigned int location : 2; // Is the span on a freelist, and if so, which?
- unsigned int sample : 1; // Sampled object?
-
-#undef SPAN_HISTORY
-#ifdef SPAN_HISTORY
- // For debugging, we can keep a log events per span
- int nexthistory;
- char history[64];
- int value[64];
-#endif
-
- // What freelist the span is on: IN_USE if on none, or normal or returned
- enum { IN_USE, ON_NORMAL_FREELIST, ON_RETURNED_FREELIST };
-};
-
-#ifdef SPAN_HISTORY
-void Event(Span* span, char op, int v = 0);
-#else
-#define Event(s,o,v) ((void) 0)
-#endif
-
-// Allocator/deallocator for spans
-Span* NewSpan(PageID p, Length len);
-void DeleteSpan(Span* span);
-
-// -------------------------------------------------------------------------
-// Doubly linked list of spans.
-// -------------------------------------------------------------------------
-
-// Initialize *list to an empty list.
-void DLL_Init(Span* list);
-
-// Remove 'span' from the linked list in which it resides, updating the
-// pointers of adjacent Spans and setting span's next and prev to NULL.
-void DLL_Remove(Span* span);
-
-// Return true iff "list" is empty.
-inline bool DLL_IsEmpty(const Span* list) {
- return list->next == list;
-}
-
-// Add span to the front of list.
-void DLL_Prepend(Span* list, Span* span);
-
-// Return the length of the linked list. O(n)
-int DLL_Length(const Span* list);
-
-} // namespace tcmalloc
-
-#endif // TCMALLOC_SPAN_H_
diff --git a/src/third_party/gperftools-2.5/src/stack_trace_table.cc b/src/third_party/gperftools-2.5/src/stack_trace_table.cc
deleted file mode 100644
index 1862124af3c..00000000000
--- a/src/third_party/gperftools-2.5/src/stack_trace_table.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2009, 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: Andrew Fikes
-
-#include <config.h>
-#include "stack_trace_table.h"
-#include <string.h> // for NULL, memset
-#include "base/spinlock.h" // for SpinLockHolder
-#include "common.h" // for StackTrace
-#include "internal_logging.h" // for ASSERT, Log
-#include "page_heap_allocator.h" // for PageHeapAllocator
-#include "static_vars.h" // for Static
-
-namespace tcmalloc {
-
-bool StackTraceTable::Bucket::KeyEqual(uintptr_t h,
- const StackTrace& t) const {
- const bool eq = (this->hash == h && this->trace.depth == t.depth);
- for (int i = 0; eq && i < t.depth; ++i) {
- if (this->trace.stack[i] != t.stack[i]) {
- return false;
- }
- }
- return eq;
-}
-
-StackTraceTable::StackTraceTable()
- : error_(false),
- depth_total_(0),
- bucket_total_(0),
- table_(new Bucket*[kHashTableSize]()) {
- memset(table_, 0, kHashTableSize * sizeof(Bucket*));
-}
-
-StackTraceTable::~StackTraceTable() {
- delete[] table_;
-}
-
-void StackTraceTable::AddTrace(const StackTrace& t) {
- if (error_) {
- return;
- }
-
- // Hash function borrowed from base/heap-profile-table.cc
- uintptr_t h = 0;
- for (int i = 0; i < t.depth; ++i) {
- h += reinterpret_cast<uintptr_t>(t.stack[i]);
- h += h << 10;
- h ^= h >> 6;
- }
- h += h << 3;
- h ^= h >> 11;
-
- const int idx = h % kHashTableSize;
-
- Bucket* b = table_[idx];
- while (b != NULL && !b->KeyEqual(h, t)) {
- b = b->next;
- }
- if (b != NULL) {
- b->count++;
- b->trace.size += t.size; // keep cumulative size
- } else {
- depth_total_ += t.depth;
- bucket_total_++;
- b = Static::bucket_allocator()->New();
- if (b == NULL) {
- Log(kLog, __FILE__, __LINE__,
- "tcmalloc: could not allocate bucket", sizeof(*b));
- error_ = true;
- } else {
- b->hash = h;
- b->trace = t;
- b->count = 1;
- b->next = table_[idx];
- table_[idx] = b;
- }
- }
-}
-
-void** StackTraceTable::ReadStackTracesAndClear() {
- if (error_) {
- return NULL;
- }
-
- // Allocate output array
- const int out_len = bucket_total_ * 3 + depth_total_ + 1;
- void** out = new void*[out_len];
- if (out == NULL) {
- Log(kLog, __FILE__, __LINE__,
- "tcmalloc: allocation failed for stack traces",
- out_len * sizeof(*out));
- return NULL;
- }
-
- // Fill output array
- int idx = 0;
- for (int i = 0; i < kHashTableSize; ++i) {
- Bucket* b = table_[i];
- while (b != NULL) {
- out[idx++] = reinterpret_cast<void*>(static_cast<uintptr_t>(b->count));
- out[idx++] = reinterpret_cast<void*>(b->trace.size); // cumulative size
- out[idx++] = reinterpret_cast<void*>(b->trace.depth);
- for (int d = 0; d < b->trace.depth; ++d) {
- out[idx++] = b->trace.stack[d];
- }
- b = b->next;
- }
- }
- out[idx++] = NULL;
- ASSERT(idx == out_len);
-
- // Clear state
- error_ = false;
- depth_total_ = 0;
- bucket_total_ = 0;
- SpinLockHolder h(Static::pageheap_lock());
- for (int i = 0; i < kHashTableSize; ++i) {
- Bucket* b = table_[i];
- while (b != NULL) {
- Bucket* next = b->next;
- Static::bucket_allocator()->Delete(b);
- b = next;
- }
- table_[i] = NULL;
- }
-
- return out;
-}
-
-} // namespace tcmalloc
diff --git a/src/third_party/gperftools-2.5/src/stack_trace_table.h b/src/third_party/gperftools-2.5/src/stack_trace_table.h
deleted file mode 100644
index e2897715354..00000000000
--- a/src/third_party/gperftools-2.5/src/stack_trace_table.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2009, 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: Andrew Fikes
-//
-// Utility class for coalescing sampled stack traces. Not thread-safe.
-
-#ifndef TCMALLOC_STACK_TRACE_TABLE_H_
-#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 {
-
-class PERFTOOLS_DLL_DECL StackTraceTable {
- public:
- // REQUIRES: L < pageheap_lock
- StackTraceTable();
- ~StackTraceTable();
-
- // Adds stack trace "t" to table.
- //
- // REQUIRES: L >= pageheap_lock
- void AddTrace(const StackTrace& t);
-
- // Returns stack traces formatted per MallocExtension guidelines.
- // May return NULL on error. Clears state before returning.
- //
- // REQUIRES: L < pageheap_lock
- void** ReadStackTracesAndClear();
-
- // Exposed for PageHeapAllocator
- struct Bucket {
- // Key
- uintptr_t hash;
- StackTrace trace;
-
- // Payload
- int count;
- Bucket* next;
-
- bool KeyEqual(uintptr_t h, const StackTrace& t) const;
- };
-
- // For testing
- int depth_total() const { return depth_total_; }
- int bucket_total() const { return bucket_total_; }
-
- private:
- static const int kHashTableSize = 1 << 14; // => table_ is 128k
-
- bool error_;
- int depth_total_;
- int bucket_total_;
- Bucket** table_;
-};
-
-} // namespace tcmalloc
-
-#endif // TCMALLOC_STACK_TRACE_TABLE_H_
diff --git a/src/third_party/gperftools-2.5/src/stacktrace.cc b/src/third_party/gperftools-2.5/src/stacktrace.cc
deleted file mode 100644
index 395d569c8ca..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-//
-// Produce stack trace.
-//
-// There are three different ways we can try to get the stack trace:
-//
-// 1) Our hand-coded stack-unwinder. This depends on a certain stack
-// layout, which is used by gcc (and those systems using a
-// gcc-compatible ABI) on x86 systems, at least since gcc 2.95.
-// It uses the frame pointer to do its work.
-//
-// 2) The libunwind library. This is still in development, and as a
-// separate library adds a new dependency, abut doesn't need a frame
-// pointer. It also doesn't call malloc.
-//
-// 3) The gdb unwinder -- also the one used by the c++ exception code.
-// It's obviously well-tested, but has a fatal flaw: it can call
-// malloc() from the unwinder. This is a problem because we're
-// trying to use the unwinder to instrument malloc().
-//
-// Note: if you add a new implementation here, make sure it works
-// correctly when GetStackTrace() is called with max_depth == 0.
-// Some code may do that.
-
-#include <config.h>
-#include <stdlib.h> // for getenv
-#include <string.h> // for strcmp
-#include <stdio.h> // for fprintf
-#include "gperftools/stacktrace.h"
-#include "base/commandlineflags.h"
-#include "base/googleinit.h"
-
-
-// we're using plain struct and not class to avoid any possible issues
-// during initialization. Struct of pointers is easy to init at
-// link-time.
-struct GetStackImplementation {
- int (*GetStackFramesPtr)(void** result, int* sizes, int max_depth,
- int skip_count);
-
- int (*GetStackFramesWithContextPtr)(void** result, int* sizes, int max_depth,
- int skip_count, const void *uc);
-
- int (*GetStackTracePtr)(void** result, int max_depth,
- int skip_count);
-
- int (*GetStackTraceWithContextPtr)(void** result, int max_depth,
- int skip_count, const void *uc);
-
- const char *name;
-};
-
-#if HAVE_DECL_BACKTRACE
-#define STACKTRACE_INL_HEADER "stacktrace_generic-inl.h"
-#define GST_SUFFIX generic
-#include "stacktrace_impl_setup-inl.h"
-#undef GST_SUFFIX
-#undef STACKTRACE_INL_HEADER
-#define HAVE_GST_generic
-#endif
-
-#ifdef HAVE_UNWIND_BACKTRACE
-#define STACKTRACE_INL_HEADER "stacktrace_libgcc-inl.h"
-#define GST_SUFFIX libgcc
-#include "stacktrace_impl_setup-inl.h"
-#undef GST_SUFFIX
-#undef STACKTRACE_INL_HEADER
-#define HAVE_GST_libgcc
-#endif
-
-// libunwind uses __thread so we check for both libunwind.h and
-// __thread support
-#if defined(HAVE_LIBUNWIND_H) && defined(HAVE_TLS)
-#define STACKTRACE_INL_HEADER "stacktrace_libunwind-inl.h"
-#define GST_SUFFIX libunwind
-#include "stacktrace_impl_setup-inl.h"
-#undef GST_SUFFIX
-#undef STACKTRACE_INL_HEADER
-#define HAVE_GST_libunwind
-#endif // HAVE_LIBUNWIND_H
-
-#if defined(__i386__) || defined(__x86_64__)
-#define STACKTRACE_INL_HEADER "stacktrace_x86-inl.h"
-#define GST_SUFFIX x86
-#include "stacktrace_impl_setup-inl.h"
-#undef GST_SUFFIX
-#undef STACKTRACE_INL_HEADER
-#define HAVE_GST_x86
-#endif // i386 || x86_64
-
-#if defined(__ppc__) || defined(__PPC__)
-#if defined(__linux__)
-#define STACKTRACE_INL_HEADER "stacktrace_powerpc-linux-inl.h"
-#else
-#define STACKTRACE_INL_HEADER "stacktrace_powerpc-darwin-inl.h"
-#endif
-#define GST_SUFFIX ppc
-#include "stacktrace_impl_setup-inl.h"
-#undef GST_SUFFIX
-#undef STACKTRACE_INL_HEADER
-#define HAVE_GST_ppc
-#endif
-
-#if defined(__arm__)
-#define STACKTRACE_INL_HEADER "stacktrace_arm-inl.h"
-#define GST_SUFFIX arm
-#include "stacktrace_impl_setup-inl.h"
-#undef GST_SUFFIX
-#undef STACKTRACE_INL_HEADER
-#define HAVE_GST_arm
-#endif
-
-#ifdef TCMALLOC_ENABLE_INSTRUMENT_STACKTRACE
-#define STACKTRACE_INL_HEADER "stacktrace_instrument-inl.h"
-#define GST_SUFFIX instrument
-#include "stacktrace_impl_setup-inl.h"
-#undef GST_SUFFIX
-#undef STACKTRACE_INL_HEADER
-#define HAVE_GST_instrument
-#endif
-
-// The Windows case -- probably cygwin and mingw will use one of the
-// x86-includes above, but if not, we can fall back to windows intrinsics.
-#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__)
-#define STACKTRACE_INL_HEADER "stacktrace_win32-inl.h"
-#define GST_SUFFIX win32
-#include "stacktrace_impl_setup-inl.h"
-#undef GST_SUFFIX
-#undef STACKTRACE_INL_HEADER
-#define HAVE_GST_win32
-#endif
-
-static GetStackImplementation *all_impls[] = {
-#ifdef HAVE_GST_libgcc
- &impl__libgcc,
-#endif
-#ifdef HAVE_GST_generic
- &impl__generic,
-#endif
-#ifdef HAVE_GST_libunwind
- &impl__libunwind,
-#endif
-#ifdef HAVE_GST_x86
- &impl__x86,
-#endif
-#ifdef HAVE_GST_arm
- &impl__arm,
-#endif
-#ifdef HAVE_GST_ppc
- &impl__ppc,
-#endif
-#ifdef HAVE_GST_instrument
- &impl__instrument,
-#endif
-#ifdef HAVE_GST_win32
- &impl__win32,
-#endif
- NULL
-};
-
-// ppc and i386 implementations prefer arch-specific asm implementations.
-// arm's asm implementation is broken
-#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__PPC__)
-#if !defined(NO_FRAME_POINTER)
-#define TCMALLOC_DONT_PREFER_LIBUNWIND
-#endif
-#endif
-
-static bool get_stack_impl_inited;
-
-#if defined(HAVE_GST_instrument)
-static GetStackImplementation *get_stack_impl = &impl__instrument;
-#elif defined(HAVE_GST_win32)
-static GetStackImplementation *get_stack_impl = &impl__win32;
-#elif defined(HAVE_GST_x86) && defined(TCMALLOC_DONT_PREFER_LIBUNWIND)
-static GetStackImplementation *get_stack_impl = &impl__x86;
-#elif defined(HAVE_GST_ppc) && defined(TCMALLOC_DONT_PREFER_LIBUNWIND)
-static GetStackImplementation *get_stack_impl = &impl__ppc;
-#elif defined(HAVE_GST_libunwind)
-static GetStackImplementation *get_stack_impl = &impl__libunwind;
-#elif defined(HAVE_GST_libgcc)
-static GetStackImplementation *get_stack_impl = &impl__libgcc;
-#elif defined(HAVE_GST_generic)
-static GetStackImplementation *get_stack_impl = &impl__generic;
-#elif defined(HAVE_GST_arm)
-static GetStackImplementation *get_stack_impl = &impl__arm;
-#elif 0
-// This is for the benefit of code analysis tools that may have
-// trouble with the computed #include above.
-# include "stacktrace_x86-inl.h"
-# include "stacktrace_libunwind-inl.h"
-# include "stacktrace_generic-inl.h"
-# include "stacktrace_powerpc-inl.h"
-# include "stacktrace_win32-inl.h"
-# include "stacktrace_arm-inl.h"
-# include "stacktrace_instrument-inl.h"
-#else
-#error Cannot calculate stack trace: will need to write for your environment
-#endif
-
-static int ATTRIBUTE_NOINLINE frame_forcer(int rv) {
- return rv;
-}
-
-static void init_default_stack_impl_inner(void);
-
-namespace tcmalloc {
- bool EnterStacktraceScope(void);
- void LeaveStacktraceScope(void);
-}
-
-namespace {
- using tcmalloc::EnterStacktraceScope;
- using tcmalloc::LeaveStacktraceScope;
-
- class StacktraceScope {
- bool stacktrace_allowed;
- public:
- StacktraceScope() {
- stacktrace_allowed = true;
- stacktrace_allowed = EnterStacktraceScope();
- }
- bool IsStacktraceAllowed() {
- return stacktrace_allowed;
- }
- ~StacktraceScope() {
- if (stacktrace_allowed) {
- LeaveStacktraceScope();
- }
- }
- };
-}
-
-PERFTOOLS_DLL_DECL int GetStackFrames(void** result, int* sizes, int max_depth,
- int skip_count) {
- StacktraceScope scope;
- if (!scope.IsStacktraceAllowed()) {
- return 0;
- }
- init_default_stack_impl_inner();
- return frame_forcer(get_stack_impl->GetStackFramesPtr(result, sizes, max_depth, skip_count));
-}
-
-PERFTOOLS_DLL_DECL int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
- int skip_count, const void *uc) {
- StacktraceScope scope;
- if (!scope.IsStacktraceAllowed()) {
- return 0;
- }
- init_default_stack_impl_inner();
- return frame_forcer(get_stack_impl->GetStackFramesWithContextPtr(
- result, sizes, max_depth,
- skip_count, uc));
-}
-
-PERFTOOLS_DLL_DECL int GetStackTrace(void** result, int max_depth,
- int skip_count) {
- StacktraceScope scope;
- if (!scope.IsStacktraceAllowed()) {
- return 0;
- }
- init_default_stack_impl_inner();
- return frame_forcer(get_stack_impl->GetStackTracePtr(result, max_depth, skip_count));
-}
-
-PERFTOOLS_DLL_DECL int GetStackTraceWithContext(void** result, int max_depth,
- int skip_count, const void *uc) {
- StacktraceScope scope;
- if (!scope.IsStacktraceAllowed()) {
- return 0;
- }
- init_default_stack_impl_inner();
- return frame_forcer(get_stack_impl->GetStackTraceWithContextPtr(
- result, max_depth, skip_count, uc));
-}
-
-static void init_default_stack_impl_inner(void) {
- if (get_stack_impl_inited) {
- return;
- }
- get_stack_impl_inited = true;
- char *val = getenv("TCMALLOC_STACKTRACE_METHOD");
- if (!val || !*val) {
- return;
- }
- for (GetStackImplementation **p = all_impls; *p; p++) {
- GetStackImplementation *c = *p;
- if (strcmp(c->name, val) == 0) {
- get_stack_impl = c;
- return;
- }
- }
- fprintf(stderr, "Unknown or unsupported stacktrace method requested: %s. Ignoring it\n", val);
-}
-
-static void init_default_stack_impl(void) {
- init_default_stack_impl_inner();
- if (EnvToBool("TCMALLOC_STACKTRACE_METHOD_VERBOSE", false)) {
- fprintf(stderr, "Chosen stacktrace method is %s\nSupported methods:\n", get_stack_impl->name);
- for (GetStackImplementation **p = all_impls; *p; p++) {
- GetStackImplementation *c = *p;
- fprintf(stderr, "* %s\n", c->name);
- }
- fputs("\n", stderr);
- }
-}
-
-REGISTER_MODULE_INITIALIZER(stacktrace_init_default_stack_impl, init_default_stack_impl());
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_arm-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_arm-inl.h
deleted file mode 100644
index 1586b8fec62..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_arm-inl.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Doug Kwan
-// This is inspired by Craig Silverstein's PowerPC stacktrace code.
-//
-
-#ifndef BASE_STACKTRACE_ARM_INL_H_
-#define BASE_STACKTRACE_ARM_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-#include <stdint.h> // for uintptr_t
-#include "base/basictypes.h" // for NULL
-#include <gperftools/stacktrace.h>
-
-// WARNING:
-// This only works if all your code is in either ARM or THUMB mode. With
-// interworking, the frame pointer of the caller can either be in r11 (ARM
-// mode) or r7 (THUMB mode). A callee only saves the frame pointer of its
-// mode in a fixed location on its stack frame. If the caller is a different
-// mode, there is no easy way to find the frame pointer. It can either be
-// still in the designated register or saved on stack along with other callee
-// saved registers.
-
-// Given a pointer to a stack frame, locate and return the calling
-// stackframe, or return NULL if no stackframe can be found. Perform sanity
-// checks (the strictness of which is controlled by the boolean parameter
-// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
-template<bool STRICT_UNWINDING>
-static void **NextStackFrame(void **old_sp) {
- void **new_sp = (void**) old_sp[-1];
-
- // Check that the transition from frame pointer old_sp to frame
- // pointer new_sp isn't clearly bogus
- if (STRICT_UNWINDING) {
- // With the stack growing downwards, older stack frame must be
- // at a greater address that the current one.
- if (new_sp <= old_sp) return NULL;
- // Assume stack frames larger than 100,000 bytes are bogus.
- if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
- } else {
- // In the non-strict mode, allow discontiguous stack frames.
- // (alternate-signal-stacks for example).
- if (new_sp == old_sp) return NULL;
- // And allow frames upto about 1MB.
- if ((new_sp > old_sp)
- && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
- }
- if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
- return new_sp;
-}
-
-// This ensures that GetStackTrace stes up the Link Register properly.
-#ifdef __GNUC__
-void StacktraceArmDummyFunction() __attribute__((noinline));
-void StacktraceArmDummyFunction() { __asm__ volatile(""); }
-#else
-# error StacktraceArmDummyFunction() needs to be ported to this platform.
-#endif
-#endif // BASE_STACKTRACE_ARM_INL_H_
-
-// Note: this part of the file is included several times.
-// Do not put globals below.
-
-// The following 4 functions are generated from the code below:
-// GetStack{Trace,Frames}()
-// GetStack{Trace,Frames}WithContext()
-//
-// These functions take the following args:
-// void** result: the stack-trace, as an array
-// int* sizes: the size of each stack frame, as an array
-// (GetStackFrames* only)
-// int max_depth: the size of the result (and sizes) array(s)
-// int skip_count: how many stack pointers to skip before storing in result
-// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
-static int GET_STACK_TRACE_OR_FRAMES {
-#ifdef __GNUC__
- void **sp = reinterpret_cast<void**>(__builtin_frame_address(0));
-#else
-# error reading stack point not yet supported on this platform.
-#endif
-
- // On ARM, the return address is stored in the link register (r14).
- // This is not saved on the stack frame of a leaf function. To
- // simplify code that reads return addresses, we call a dummy
- // function so that the return address of this function is also
- // stored in the stack frame. This works at least for gcc.
- StacktraceArmDummyFunction();
-
- skip_count++; // skip parent frame due to indirection in stacktrace.cc
-
- int n = 0;
- while (sp && n < max_depth) {
- // The GetStackFrames routine is called when we are in some
- // informational context (the failure signal handler for example).
- // Use the non-strict unwinding rules to produce a stack trace
- // that is as complete as possible (even if it contains a few bogus
- // entries in some rare cases).
- void **next_sp = NextStackFrame<IS_STACK_FRAMES == 0>(sp);
-
- if (skip_count > 0) {
- skip_count--;
- } else {
- result[n] = *sp;
-
-#if IS_STACK_FRAMES
- if (next_sp > sp) {
- sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp;
- } else {
- // A frame-size of 0 is used to indicate unknown frame size.
- sizes[n] = 0;
- }
-#endif
- n++;
- }
- sp = next_sp;
- }
- return n;
-}
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_generic-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_generic-inl.h
deleted file mode 100644
index 7d7c22d9e45..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_generic-inl.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-//
-// Portable implementation - just use glibc
-//
-// Note: The glibc implementation may cause a call to malloc.
-// This can cause a deadlock in HeapProfiler.
-
-#ifndef BASE_STACKTRACE_GENERIC_INL_H_
-#define BASE_STACKTRACE_GENERIC_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-#include <execinfo.h>
-#include <string.h>
-#include "gperftools/stacktrace.h"
-#endif // BASE_STACKTRACE_GENERIC_INL_H_
-
-// Note: this part of the file is included several times.
-// Do not put globals below.
-
-// The following 4 functions are generated from the code below:
-// GetStack{Trace,Frames}()
-// GetStack{Trace,Frames}WithContext()
-//
-// These functions take the following args:
-// void** result: the stack-trace, as an array
-// int* sizes: the size of each stack frame, as an array
-// (GetStackFrames* only)
-// int max_depth: the size of the result (and sizes) array(s)
-// int skip_count: how many stack pointers to skip before storing in result
-// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
-static int GET_STACK_TRACE_OR_FRAMES {
- static const int kStackLength = 64;
- void * stack[kStackLength];
- int size;
-
- size = backtrace(stack, kStackLength);
- skip_count += 2; // we want to skip the current and it's parent frame as well
- int result_count = size - skip_count;
- if (result_count < 0)
- result_count = 0;
- if (result_count > max_depth)
- result_count = max_depth;
- for (int i = 0; i < result_count; i++)
- result[i] = stack[i + skip_count];
-
-#if IS_STACK_FRAMES
- // No implementation for finding out the stack frame sizes yet.
- memset(sizes, 0, sizeof(*sizes) * result_count);
-#endif
-
- return result_count;
-}
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_impl_setup-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_impl_setup-inl.h
deleted file mode 100644
index 698c5b38196..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_impl_setup-inl.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// NOTE: this is NOT to be #include-d normally. It's internal
-// implementation detail of stacktrace.cc
-//
-
-// Copyright (c) 2014, gperftools Contributors.
-// 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: Aliaksey Kandratsenka <alk@tut.by>
-//
-// based on stacktrace.cc and stacktrace_config.h by Sanjay Ghemawat
-// and Paul Pluzhnikov from Google Inc
-
-#define SIS_CONCAT2(a, b) a##b
-#define SIS_CONCAT(a, b) SIS_CONCAT2(a,b)
-
-#define SIS_STRINGIFY(a) SIS_STRINGIFY2(a)
-#define SIS_STRINGIFY2(a) #a
-
-#define IS_STACK_FRAMES 0
-#define IS_WITH_CONTEXT 0
-#define GET_STACK_TRACE_OR_FRAMES \
- SIS_CONCAT(GetStackTrace_, GST_SUFFIX)(void **result, int max_depth, int skip_count)
-#include STACKTRACE_INL_HEADER
-#undef IS_STACK_FRAMES
-#undef IS_WITH_CONTEXT
-#undef GET_STACK_TRACE_OR_FRAMES
-
-#define IS_STACK_FRAMES 1
-#define IS_WITH_CONTEXT 0
-#define GET_STACK_TRACE_OR_FRAMES \
- SIS_CONCAT(GetStackFrames_, GST_SUFFIX)(void **result, int *sizes, int max_depth, int skip_count)
-#include STACKTRACE_INL_HEADER
-#undef IS_STACK_FRAMES
-#undef IS_WITH_CONTEXT
-#undef GET_STACK_TRACE_OR_FRAMES
-
-#define IS_STACK_FRAMES 0
-#define IS_WITH_CONTEXT 1
-#define GET_STACK_TRACE_OR_FRAMES \
- SIS_CONCAT(GetStackTraceWithContext_, GST_SUFFIX)(void **result, int max_depth, \
- int skip_count, const void *ucp)
-#include STACKTRACE_INL_HEADER
-#undef IS_STACK_FRAMES
-#undef IS_WITH_CONTEXT
-#undef GET_STACK_TRACE_OR_FRAMES
-
-#define IS_STACK_FRAMES 1
-#define IS_WITH_CONTEXT 1
-#define GET_STACK_TRACE_OR_FRAMES \
- SIS_CONCAT(GetStackFramesWithContext_, GST_SUFFIX)(void **result, int *sizes, int max_depth, \
- int skip_count, const void *ucp)
-#include STACKTRACE_INL_HEADER
-#undef IS_STACK_FRAMES
-#undef IS_WITH_CONTEXT
-#undef GET_STACK_TRACE_OR_FRAMES
-
-static GetStackImplementation SIS_CONCAT(impl__,GST_SUFFIX) = {
- SIS_CONCAT(GetStackFrames_, GST_SUFFIX),
- SIS_CONCAT(GetStackFramesWithContext_, GST_SUFFIX),
- SIS_CONCAT(GetStackTrace_, GST_SUFFIX),
- SIS_CONCAT(GetStackTraceWithContext_, GST_SUFFIX),
- SIS_STRINGIFY(GST_SUFFIX)
-};
-
-#undef SIS_CONCAT2
-#undef SIS_CONCAT
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_instrument-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_instrument-inl.h
deleted file mode 100755
index c631765c8a2..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_instrument-inl.h
+++ /dev/null
@@ -1,155 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2013, 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: Jean Lee <xiaoyur347@gmail.com>
-// based on gcc Code-Gen-Options "-finstrument-functions" listed in
-// http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html .
-// Should run configure with CXXFLAGS="-finstrument-functions".
-
-// This file is a backtrace implementation for systems :
-// * The glibc implementation of backtrace() may cause a call to malloc,
-// and cause a deadlock in HeapProfiler.
-// * The libunwind implementation prints no backtrace.
-
-// The backtrace arrays are stored in "thread_back_trace" variable.
-// Maybe to use thread local storage is better and should save memorys.
-
-#ifndef BASE_STACKTRACE_INSTRUMENT_INL_H_
-#define BASE_STACKTRACE_INSTRUMENT_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-#include <execinfo.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include "gperftools/stacktrace.h"
-
-#define gettid() syscall(__NR_gettid)
-#ifndef __x86_64__
-#define MAX_THREAD (32768)
-#else
-#define MAX_THREAD (65536)
-#endif
-#define MAX_DEPTH (30)
-#define ATTRIBUTE_NOINSTRUMENT __attribute__ ((no_instrument_function))
-
-typedef struct {
- int stack_depth;
- void* frame[MAX_DEPTH];
-}BACK_TRACE;
-
-static BACK_TRACE thread_back_trace[MAX_THREAD];
-extern "C" {
-void __cyg_profile_func_enter(void *func_address,
- void *call_site) ATTRIBUTE_NOINSTRUMENT;
-void __cyg_profile_func_enter(void *func_address, void *call_site) {
- (void)func_address;
-
- BACK_TRACE* backtrace = thread_back_trace + gettid();
- int stack_depth = backtrace->stack_depth;
- backtrace->stack_depth = stack_depth + 1;
- if ( stack_depth >= MAX_DEPTH ) {
- return;
- }
- backtrace->frame[stack_depth] = call_site;
-}
-
-void __cyg_profile_func_exit(void *func_address,
- void *call_site) ATTRIBUTE_NOINSTRUMENT;
-void __cyg_profile_func_exit(void *func_address, void *call_site) {
- (void)func_address;
- (void)call_site;
-
- BACK_TRACE* backtrace = thread_back_trace + gettid();
- int stack_depth = backtrace->stack_depth;
- backtrace->stack_depth = stack_depth - 1;
- if ( stack_depth >= MAX_DEPTH ) {
- return;
- }
- backtrace->frame[stack_depth] = 0;
-}
-} // extern "C"
-
-static int cyg_backtrace(void **buffer, int size) {
- BACK_TRACE* backtrace = thread_back_trace + gettid();
- int stack_depth = backtrace->stack_depth;
- if ( stack_depth >= MAX_DEPTH ) {
- stack_depth = MAX_DEPTH;
- }
- int nSize = (size > stack_depth) ? stack_depth : size;
- for (int i = 0; i < nSize; i++) {
- buffer[i] = backtrace->frame[nSize - i - 1];
- }
-
- return nSize;
-}
-
-#endif // BASE_STACKTRACE_INSTRUMENT_INL_H_
-
-
-// Note: this part of the file is included several times.
-// Do not put globals below.
-
-// The following 4 functions are generated from the code below:
-// GetStack{Trace,Frames}()
-// GetStack{Trace,Frames}WithContext()
-//
-// These functions take the following args:
-// void** result: the stack-trace, as an array
-// int* sizes: the size of each stack frame, as an array
-// (GetStackFrames* only)
-// int max_depth: the size of the result (and sizes) array(s)
-// int skip_count: how many stack pointers to skip before storing in result
-// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
-static int GET_STACK_TRACE_OR_FRAMES {
- static const int kStackLength = 64;
- void * stack[kStackLength];
- int size;
- memset(stack, 0, sizeof(stack));
-
- size = cyg_backtrace(stack, kStackLength);
- skip_count += 2; // we want to skip the current and parent frame as well
- int result_count = size - skip_count;
- if (result_count < 0)
- result_count = 0;
- if (result_count > max_depth)
- result_count = max_depth;
- for (int i = 0; i < result_count; i++)
- result[i] = stack[i + skip_count];
-
-#if IS_STACK_FRAMES
- // No implementation for finding out the stack frame sizes yet.
- memset(sizes, 0, sizeof(*sizes) * result_count);
-#endif
-
- return result_count;
-}
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_libgcc-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_libgcc-inl.h
deleted file mode 100644
index ce9cf5196ad..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_libgcc-inl.h
+++ /dev/null
@@ -1,111 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2016, gperftools Contributors
-// 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.
-
-// This file implements backtrace capturing via libgcc's
-// _Unwind_Backtrace. This generally works almost always. It will fail
-// sometimes when we're trying to capture backtrace from signal
-// handler (i.e. in cpu profiler) while some C++ code is throwing
-// exception.
-
-#ifndef BASE_STACKTRACE_LIBGCC_INL_H_
-#define BASE_STACKTRACE_LIBGCC_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-extern "C" {
-#include <assert.h>
-#include <string.h> // for memset()
-}
-
-#include <unwind.h>
-
-#include "gperftools/stacktrace.h"
-
-struct libgcc_backtrace_data {
- void **array;
- int skip;
- int pos;
- int limit;
-};
-
-static _Unwind_Reason_Code libgcc_backtrace_helper(struct _Unwind_Context *ctx,
- void *_data) {
- libgcc_backtrace_data *data =
- reinterpret_cast<libgcc_backtrace_data *>(_data);
-
- if (data->skip > 0) {
- data->skip--;
- return _URC_NO_REASON;
- }
-
- if (data->pos < data->limit) {
- void *ip = reinterpret_cast<void *>(_Unwind_GetIP(ctx));;
- data->array[data->pos++] = ip;
- }
-
- return _URC_NO_REASON;
-}
-
-#endif // BASE_STACKTRACE_LIBGCC_INL_H_
-
-// Note: this part of the file is included several times.
-// Do not put globals below.
-
-// The following 4 functions are generated from the code below:
-// GetStack{Trace,Frames}()
-// GetStack{Trace,Frames}WithContext()
-//
-// These functions take the following args:
-// void** result: the stack-trace, as an array
-// int* sizes: the size of each stack frame, as an array
-// (GetStackFrames* only)
-// int max_depth: the size of the result (and sizes) array(s)
-// int skip_count: how many stack pointers to skip before storing in result
-// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
-static int GET_STACK_TRACE_OR_FRAMES {
- libgcc_backtrace_data data;
- data.array = result;
- // we're also skipping current and parent's frame
- data.skip = skip_count + 2;
- data.pos = 0;
- data.limit = max_depth;
-
- _Unwind_Backtrace(libgcc_backtrace_helper, &data);
-
- if (data.pos > 1 && data.array[data.pos - 1] == NULL)
- --data.pos;
-
-#if IS_STACK_FRAMES
- // No implementation for finding out the stack frame sizes.
- memset(sizes, 0, sizeof(*sizes) * data.pos);
-#endif
-
- return data.pos;
-}
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_libunwind-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_libunwind-inl.h
deleted file mode 100644
index 8a4a731b143..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_libunwind-inl.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Arun Sharma
-//
-// Produce stack trace using libunwind
-
-#ifndef BASE_STACKTRACE_LIBINWIND_INL_H_
-#define BASE_STACKTRACE_LIBINWIND_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-// We only need local unwinder.
-#define UNW_LOCAL_ONLY
-
-extern "C" {
-#include <assert.h>
-#include <string.h> // for memset()
-#include <libunwind.h>
-}
-#include "gperftools/stacktrace.h"
-#include "base/logging.h"
-
-// Sometimes, we can try to get a stack trace from within a stack
-// trace, because libunwind can call mmap (maybe indirectly via an
-// internal mmap based memory allocator), and that mmap gets trapped
-// and causes a stack-trace request. If were to try to honor that
-// recursive request, we'd end up with infinite recursion or deadlock.
-// Luckily, it's safe to ignore those subsequent traces. In such
-// cases, we return 0 to indicate the situation.
-static __thread int recursive;
-
-#if defined(TCMALLOC_ENABLE_UNWIND_FROM_UCONTEXT) && (defined(__i386__) || defined(__x86_64__)) && defined(__GNU_LIBRARY__)
-#define BASE_STACKTRACE_UNW_CONTEXT_IS_UCONTEXT 1
-#endif
-
-#endif // BASE_STACKTRACE_LIBINWIND_INL_H_
-
-// Note: this part of the file is included several times.
-// Do not put globals below.
-
-// The following 4 functions are generated from the code below:
-// GetStack{Trace,Frames}()
-// GetStack{Trace,Frames}WithContext()
-//
-// These functions take the following args:
-// void** result: the stack-trace, as an array
-// int* sizes: the size of each stack frame, as an array
-// (GetStackFrames* only)
-// int max_depth: the size of the result (and sizes) array(s)
-// int skip_count: how many stack pointers to skip before storing in result
-// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
-static int GET_STACK_TRACE_OR_FRAMES {
- void *ip;
- int n = 0;
- unw_cursor_t cursor;
- unw_context_t uc;
-#if IS_STACK_FRAMES
- unw_word_t sp = 0, next_sp = 0;
-#endif
-
- if (recursive) {
- return 0;
- }
- ++recursive;
-
-#if (IS_WITH_CONTEXT && defined(BASE_STACKTRACE_UNW_CONTEXT_IS_UCONTEXT))
- if (ucp) {
- uc = *(static_cast<unw_context_t *>(const_cast<void *>(ucp)));
- /* this is a bit weird. profiler.cc calls us with signal's ucontext
- * yet passing us 2 as skip_count and essentially assuming we won't
- * use ucontext. */
- /* In order to fix that I'm going to assume that if ucp is
- * non-null we're asked to ignore skip_count in case we're
- * able to use ucp */
- skip_count = 0;
- } else {
- unw_getcontext(&uc);
- skip_count += 2; // Do not include current and parent frame
- }
-#else
- unw_getcontext(&uc);
- skip_count += 2; // Do not include current and parent frame
-#endif
-
- int ret = unw_init_local(&cursor, &uc);
- assert(ret >= 0);
-
- while (skip_count--) {
- if (unw_step(&cursor) <= 0) {
- goto out;
- }
-#if IS_STACK_FRAMES
- if (unw_get_reg(&cursor, UNW_REG_SP, &next_sp)) {
- goto out;
- }
-#endif
- }
-
- while (n < max_depth) {
- if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip) < 0) {
- break;
- }
-#if IS_STACK_FRAMES
- sizes[n] = 0;
-#endif
- result[n++] = ip;
- if (unw_step(&cursor) <= 0) {
- break;
- }
-#if IS_STACK_FRAMES
- sp = next_sp;
- if (unw_get_reg(&cursor, UNW_REG_SP, &next_sp) , 0) {
- break;
- }
- sizes[n - 1] = next_sp - sp;
-#endif
- }
-out:
- --recursive;
- return n;
-}
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_powerpc-darwin-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_powerpc-darwin-inl.h
deleted file mode 100644
index c4c2edbc535..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_powerpc-darwin-inl.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (c) 2007, 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.
-
-// ---
-// Produce stack trace. ABI documentation reference can be found at:
-// * PowerPC32 ABI: https://www.power.org/documentation/
-// power-architecture-32-bit-abi-supplement-1-0-embeddedlinuxunified/
-// * PowerPC64 ABI:
-// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
-
-#ifndef BASE_STACKTRACE_POWERPC_INL_H_
-#define BASE_STACKTRACE_POWERPC_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-#include <stdint.h> // for uintptr_t
-#include <stdlib.h> // for NULL
-#include <gperftools/stacktrace.h>
-
-// Given a pointer to a stack frame, locate and return the calling
-// stackframe, or return NULL if no stackframe can be found. Perform sanity
-// checks (the strictness of which is controlled by the boolean parameter
-// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
-template<bool STRICT_UNWINDING>
-static void **NextStackFrame(void **old_sp) {
- void **new_sp = (void **) *old_sp;
-
- // Check that the transition from frame pointer old_sp to frame
- // pointer new_sp isn't clearly bogus
- if (STRICT_UNWINDING) {
- // With the stack growing downwards, older stack frame must be
- // at a greater address that the current one.
- if (new_sp <= old_sp) return NULL;
- // Assume stack frames larger than 100,000 bytes are bogus.
- if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
- } else {
- // In the non-strict mode, allow discontiguous stack frames.
- // (alternate-signal-stacks for example).
- if (new_sp == old_sp) return NULL;
- // And allow frames upto about 1MB.
- if ((new_sp > old_sp)
- && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
- }
- if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
- return new_sp;
-}
-
-// This ensures that GetStackTrace stes up the Link Register properly.
-void StacktracePowerPCDummyFunction() __attribute__((noinline));
-void StacktracePowerPCDummyFunction() { __asm__ volatile(""); }
-#endif // BASE_STACKTRACE_POWERPC_INL_H_
-
-// Note: this part of the file is included several times.
-// Do not put globals below.
-
-// The following 4 functions are generated from the code below:
-// GetStack{Trace,Frames}()
-// GetStack{Trace,Frames}WithContext()
-//
-// These functions take the following args:
-// void** result: the stack-trace, as an array
-// int* sizes: the size of each stack frame, as an array
-// (GetStackFrames* only)
-// int max_depth: the size of the result (and sizes) array(s)
-// int skip_count: how many stack pointers to skip before storing in result
-// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
-int GET_STACK_TRACE_OR_FRAMES {
- void **sp;
- // Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther)
- // and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a
- // different asm syntax. I don't know quite the best way to discriminate
- // systems using the old as from the new one; I've gone with __APPLE__.
- // TODO(csilvers): use autoconf instead, to look for 'as --version' == 1 or 2
- __asm__ volatile ("mr %0,r1" : "=r" (sp));
-
- // On PowerPC, the "Link Register" or "Link Record" (LR), is a stack
- // entry that holds the return address of the subroutine call (what
- // instruction we run after our function finishes). This is the
- // same as the stack-pointer of our parent routine, which is what we
- // want here. While the compiler will always(?) set up LR for
- // subroutine calls, it may not for leaf functions (such as this one).
- // This routine forces the compiler (at least gcc) to push it anyway.
- StacktracePowerPCDummyFunction();
-
-#if IS_STACK_FRAMES
- // Note we do *not* increment skip_count here for the SYSV ABI. If
- // we did, the list of stack frames wouldn't properly match up with
- // the list of return addresses. Note this means the top pc entry
- // is probably bogus for linux/ppc (and other SYSV-ABI systems).
-#else
- // The LR save area is used by the callee, so the top entry is bogus.
- skip_count++;
-#endif
-
- int n = 0;
- while (sp && n < max_depth) {
- // The GetStackFrames routine is called when we are in some
- // informational context (the failure signal handler for example).
- // Use the non-strict unwinding rules to produce a stack trace
- // that is as complete as possible (even if it contains a few
- // bogus entries in some rare cases).
- void **next_sp = NextStackFrame<!IS_STACK_FRAMES>(sp);
-
- if (skip_count > 0) {
- skip_count--;
- } else {
- // PowerPC has 3 main ABIs, which say where in the stack the
- // Link Register is. For DARWIN and AIX (used by apple and
- // linux ppc64), it's in sp[2]. For SYSV (used by linux ppc),
- // it's in sp[1].
-#if defined(__PPC64__)
- // This check is in case the compiler doesn't define _CALL_AIX/etc.
- result[n] = *(sp+2);
-#elif defined(__linux)
- // This check is in case the compiler doesn't define _CALL_SYSV.
- result[n] = *(sp+1);
-#endif
-
-#if IS_STACK_FRAMES
- if (next_sp > sp) {
- sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp;
- } else {
- // A frame-size of 0 is used to indicate unknown frame size.
- sizes[n] = 0;
- }
-#endif
- n++;
- }
- sp = next_sp;
- }
- return n;
-}
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_powerpc-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_powerpc-inl.h
deleted file mode 100644
index 811d6cc97ee..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_powerpc-inl.h
+++ /dev/null
@@ -1,176 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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
-//
-// Produce stack trace. I'm guessing (hoping!) the code is much like
-// for x86. For apple machines, at least, it seems to be; see
-// http://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
-// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
-// Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882
-
-#ifndef BASE_STACKTRACE_POWERPC_INL_H_
-#define BASE_STACKTRACE_POWERPC_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-#include <stdint.h> // for uintptr_t
-#include <stdlib.h> // for NULL
-#include <gperftools/stacktrace.h>
-
-struct layout_ppc {
- struct layout_ppc *next;
-#if defined(__APPLE__) || (defined(__linux) && defined(__PPC64__))
- long condition_register;
-#endif
- void *return_addr;
-};
-
-// Given a pointer to a stack frame, locate and return the calling
-// stackframe, or return NULL if no stackframe can be found. Perform sanity
-// checks (the strictness of which is controlled by the boolean parameter
-// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
-template<bool STRICT_UNWINDING>
-static layout_ppc *NextStackFrame(layout_ppc *current) {
- uintptr_t old_sp = (uintptr_t)(current);
- uintptr_t new_sp = (uintptr_t)(current->next);
-
- // Check that the transition from frame pointer old_sp to frame
- // pointer new_sp isn't clearly bogus
- if (STRICT_UNWINDING) {
- // With the stack growing downwards, older stack frame must be
- // at a greater address that the current one.
- if (new_sp <= old_sp)
- return NULL;
- // Assume stack frames larger than 100,000 bytes are bogus.
- if (new_sp - old_sp > 100000)
- return NULL;
- } else {
- // In the non-strict mode, allow discontiguous stack frames.
- // (alternate-signal-stacks for example).
- if (new_sp == old_sp)
- return NULL;
- // And allow frames upto about 1MB.
- if ((new_sp > old_sp) && (new_sp - old_sp > 1000000))
- return NULL;
- }
- if (new_sp & (sizeof(void *) - 1))
- return NULL;
- return current->next;
-}
-
-// This ensures that GetStackTrace stes up the Link Register properly.
-void StacktracePowerPCDummyFunction() __attribute__((noinline));
-void StacktracePowerPCDummyFunction() { __asm__ volatile(""); }
-#endif // BASE_STACKTRACE_POWERPC_INL_H_
-
-// Note: this part of the file is included several times.
-// Do not put globals below.
-
-// Load instruction used on top-of-stack get.
-#if defined(__PPC64__) || defined(__LP64__)
-# define LOAD "ld"
-#else
-# define LOAD "lwz"
-#endif
-
-#if defined(__linux__) && defined(__PPC__)
-# define TOP_STACK "%0,0(1)"
-#elif defined(__MACH__) && defined(__APPLE__)
-// Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther)
-// and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a
-// different asm syntax. I don't know quite the best way to discriminate
-// systems using the old as from the new one; I've gone with __APPLE__.
-// TODO(csilvers): use autoconf instead, to look for 'as --version' == 1 or 2
-# define TOP_STACK "%0,0(r1)"
-#endif
-
-
-
-// The following 4 functions are generated from the code below:
-// GetStack{Trace,Frames}()
-// GetStack{Trace,Frames}WithContext()
-//
-// These functions take the following args:
-// void** result: the stack-trace, as an array
-// int* sizes: the size of each stack frame, as an array
-// (GetStackFrames* only)
-// int max_depth: the size of the result (and sizes) array(s)
-// int skip_count: how many stack pointers to skip before storing in result
-// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
-static int GET_STACK_TRACE_OR_FRAMES {
- layout_ppc *current;
- int n;
-
- // Force GCC to spill LR.
- asm volatile ("" : "=l"(current));
-
- // Get the address on top-of-stack
- asm volatile (LOAD " " TOP_STACK : "=r"(current));
-
- StacktracePowerPCDummyFunction();
-
- n = 0;
- skip_count++; // skip parent's frame due to indirection in
- // stacktrace.cc
- while (current && n < max_depth) {
-
- // The GetStackFrames routine is called when we are in some
- // informational context (the failure signal handler for example).
- // Use the non-strict unwinding rules to produce a stack trace
- // that is as complete as possible (even if it contains a few
- // bogus entries in some rare cases).
- layout_ppc *next = NextStackFrame<!IS_STACK_FRAMES>(current);
- if (skip_count > 0) {
- skip_count--;
- } else {
- result[n] = current->return_addr;
-#if IS_STACK_FRAMES
- if (next > current) {
- sizes[n] = (uintptr_t)next - (uintptr_t)current;
- } else {
- // A frame-size of 0 is used to indicate unknown frame size.
- sizes[n] = 0;
- }
-#endif
- n++;
- }
- current = next;
- }
-
- // It's possible the second-last stack frame can't return
- // (that is, it's __libc_start_main), in which case
- // the CRT startup code will have set its LR to 'NULL'.
- if (n > 0 && result[n-1] == NULL)
- n--;
-
- return n;
-}
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_powerpc-linux-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_powerpc-linux-inl.h
deleted file mode 100644
index 430af2d30fb..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_powerpc-linux-inl.h
+++ /dev/null
@@ -1,230 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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
-//
-// Produce stack trace. ABI documentation reference can be found at:
-// * PowerPC32 ABI: https://www.power.org/documentation/
-// power-architecture-32-bit-abi-supplement-1-0-embeddedlinuxunified/
-// * PowerPC64 ABI:
-// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
-
-#ifndef BASE_STACKTRACE_POWERPC_INL_H_
-#define BASE_STACKTRACE_POWERPC_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-#include <stdint.h> // for uintptr_t
-#include <stdlib.h> // for NULL
-#include <gperftools/stacktrace.h>
-#include <base/vdso_support.h>
-
-#if defined(HAVE_SYS_UCONTEXT_H)
-#include <sys/ucontext.h>
-#elif defined(HAVE_UCONTEXT_H)
-#include <ucontext.h> // for ucontext_t
-#endif
-
-// PowerPC64 Little Endian follows BE wrt. backchain, condition register,
-// and LR save area, so no need to adjust the reading struct.
-struct layout_ppc {
- struct layout_ppc *next;
-#ifdef __PPC64__
- long condition_register;
-#endif
- void *return_addr;
-};
-
-// Signal callbacks are handled by the vDSO symbol:
-//
-// * PowerPC64 Linux (arch/powerpc/kernel/vdso64/sigtramp.S):
-// __kernel_sigtramp_rt64
-// * PowerPC32 Linux (arch/powerpc/kernel/vdso32/sigtramp.S):
-// __kernel_sigtramp32
-// __kernel_sigtramp_rt32
-//
-// So a backtrace may need to specially handling if the symbol readed is
-// the signal trampoline.
-
-// Given a pointer to a stack frame, locate and return the calling
-// stackframe, or return NULL if no stackframe can be found. Perform sanity
-// checks (the strictness of which is controlled by the boolean parameter
-// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
-template<bool STRICT_UNWINDING>
-static layout_ppc *NextStackFrame(layout_ppc *current) {
- uintptr_t old_sp = (uintptr_t)(current);
- uintptr_t new_sp = (uintptr_t)(current->next);
-
- // Check that the transition from frame pointer old_sp to frame
- // pointer new_sp isn't clearly bogus
- if (STRICT_UNWINDING) {
- // With the stack growing downwards, older stack frame must be
- // at a greater address that the current one.
- if (new_sp <= old_sp)
- return NULL;
- // Assume stack frames larger than 100,000 bytes are bogus.
- if (new_sp - old_sp > 100000)
- return NULL;
- } else {
- // In the non-strict mode, allow discontiguous stack frames.
- // (alternate-signal-stacks for example).
- if (new_sp == old_sp)
- return NULL;
- // And allow frames upto about 1MB.
- if ((new_sp > old_sp) && (new_sp - old_sp > 1000000))
- return NULL;
- }
- if (new_sp & (sizeof(void *) - 1))
- return NULL;
- return current->next;
-}
-
-// This ensures that GetStackTrace stes up the Link Register properly.
-void StacktracePowerPCDummyFunction() __attribute__((noinline));
-void StacktracePowerPCDummyFunction() { __asm__ volatile(""); }
-#endif // BASE_STACKTRACE_POWERPC_INL_H_
-
-// Note: this part of the file is included several times.
-// Do not put globals below.
-
-// Load instruction used on top-of-stack get.
-#if defined(__PPC64__) || defined(__LP64__)
-# define LOAD "ld"
-#else
-# define LOAD "lwz"
-#endif
-
-// The following 4 functions are generated from the code below:
-// GetStack{Trace,Frames}()
-// GetStack{Trace,Frames}WithContext()
-//
-// These functions take the following args:
-// void** result: the stack-trace, as an array
-// int* sizes: the size of each stack frame, as an array
-// (GetStackFrames* only)
-// int max_depth: the size of the result (and sizes) array(s)
-// int skip_count: how many stack pointers to skip before storing in result
-// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
-static int GET_STACK_TRACE_OR_FRAMES {
- layout_ppc *current;
- int n;
-
- // Get the address on top-of-stack
- current = reinterpret_cast<layout_ppc*> (__builtin_frame_address (0));
- // And ignore the current symbol
- current = current->next;
-
- StacktracePowerPCDummyFunction();
-
- n = 0;
- skip_count++; // skip parent's frame due to indirection in
- // stacktrace.cc
-
- base::VDSOSupport vdso;
- base::ElfMemImage::SymbolInfo rt_sigreturn_symbol_info;
-#ifdef __PPC64__
- const void *sigtramp64_vdso = 0;
- if (vdso.LookupSymbol("__kernel_sigtramp_rt64", "LINUX_2.6.15", STT_NOTYPE,
- &rt_sigreturn_symbol_info))
- sigtramp64_vdso = rt_sigreturn_symbol_info.address;
-#else
- const void *sigtramp32_vdso = 0;
- if (vdso.LookupSymbol("__kernel_sigtramp32", "LINUX_2.6.15", STT_NOTYPE,
- &rt_sigreturn_symbol_info))
- sigtramp32_vdso = rt_sigreturn_symbol_info.address;
- const void *sigtramp32_rt_vdso = 0;
- if (vdso.LookupSymbol("__kernel_sigtramp_rt32", "LINUX_2.6.15", STT_NOTYPE,
- &rt_sigreturn_symbol_info))
- sigtramp32_rt_vdso = rt_sigreturn_symbol_info.address;
-#endif
-
- while (current && n < max_depth) {
-
- // The GetStackFrames routine is called when we are in some
- // informational context (the failure signal handler for example).
- // Use the non-strict unwinding rules to produce a stack trace
- // that is as complete as possible (even if it contains a few
- // bogus entries in some rare cases).
- layout_ppc *next = NextStackFrame<!IS_STACK_FRAMES>(current);
- if (skip_count > 0) {
- skip_count--;
- } else {
- result[n] = current->return_addr;
-#ifdef __PPC64__
- if (sigtramp64_vdso && (sigtramp64_vdso == current->return_addr)) {
- struct signal_frame_64 {
- char dummy[128];
- ucontext_t uc;
- // We don't care about the rest, since the IP value is at 'uc' field.
- } *sigframe = reinterpret_cast<signal_frame_64*>(current);
- result[n] = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_NIP];
- }
-#else
- if (sigtramp32_vdso && (sigtramp32_vdso == current->return_addr)) {
- struct signal_frame_32 {
- char dummy[64];
- struct sigcontext sctx;
- mcontext_t mctx;
- // We don't care about the rest, since IP value is at 'mctx' field.
- } *sigframe = reinterpret_cast<signal_frame_32*>(current);
- result[n] = (void*) sigframe->mctx.gregs[PT_NIP];
- } else if (sigtramp32_rt_vdso && (sigtramp32_rt_vdso == current->return_addr)) {
- struct rt_signal_frame_32 {
- char dummy[64 + 16];
- siginfo_t info;
- struct ucontext uc;
- // We don't care about the rest, since IP value is at 'uc' field.A
- } *sigframe = reinterpret_cast<rt_signal_frame_32*>(current);
- result[n] = (void*) sigframe->uc.uc_mcontext.uc_regs->gregs[PT_NIP];
- }
-#endif
-
-#if IS_STACK_FRAMES
- if (next > current) {
- sizes[n] = (uintptr_t)next - (uintptr_t)current;
- } else {
- // A frame-size of 0 is used to indicate unknown frame size.
- sizes[n] = 0;
- }
-#endif
- n++;
- }
- current = next;
- }
-
- // It's possible the second-last stack frame can't return
- // (that is, it's __libc_start_main), in which case
- // the CRT startup code will have set its LR to 'NULL'.
- if (n > 0 && result[n-1] == NULL)
- n--;
-
- return n;
-}
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_win32-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_win32-inl.h
deleted file mode 100644
index 663e9a5bfb6..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_win32-inl.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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.
-//
-// ---
-// Produces a stack trace for Windows. Normally, one could use
-// stacktrace_x86-inl.h or stacktrace_x86_64-inl.h -- and indeed, that
-// should work for binaries compiled using MSVC in "debug" mode.
-// However, in "release" mode, Windows uses frame-pointer
-// optimization, which makes getting a stack trace very difficult.
-//
-// There are several approaches one can take. One is to use Windows
-// intrinsics like StackWalk64. These can work, but have restrictions
-// on how successful they can be. Another attempt is to write a
-// version of stacktrace_x86-inl.h that has heuristic support for
-// dealing with FPO, similar to what WinDbg does (see
-// http://www.nynaeve.net/?p=97).
-//
-// The solution we've ended up doing is to call the undocumented
-// windows function RtlCaptureStackBackTrace, which probably doesn't
-// work with FPO but at least is fast, and doesn't require a symbol
-// server.
-//
-// This code is inspired by a patch from David Vitek:
-// http://code.google.com/p/gperftools/issues/detail?id=83
-
-#ifndef BASE_STACKTRACE_WIN32_INL_H_
-#define BASE_STACKTRACE_WIN32_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-#include "config.h"
-#include <windows.h> // for GetProcAddress and GetModuleHandle
-#include <assert.h>
-
-typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
- IN ULONG frames_to_skip,
- IN ULONG frames_to_capture,
- OUT PVOID *backtrace,
- OUT PULONG backtrace_hash);
-
-// Load the function we need at static init time, where we don't have
-// to worry about someone else holding the loader's lock.
-static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
- (RtlCaptureStackBackTrace_Function*)
- GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
-
-static int GetStackTrace_win32(void** result, int max_depth,
- int skip_count) {
- if (!RtlCaptureStackBackTrace_fn) {
- // TODO(csilvers): should we log an error here?
- return 0; // can't find a stacktrace with no function to call
- }
- return (int)RtlCaptureStackBackTrace_fn(skip_count + 3, max_depth,
- result, 0);
-}
-
-static int not_implemented(void) {
- assert(0 == "Not yet implemented");
- return 0;
-}
-
-static int GetStackFrames_win32(void** /* pcs */,
- int* /* sizes */,
- int /* max_depth */,
- int /* skip_count */) {
- return not_implemented();
-}
-
-static int GetStackFramesWithContext_win32(void** result, int* sizes, int max_depth,
- int skip_count, const void *uc) {
- return not_implemented();
-}
-
-static int GetStackTraceWithContext_win32(void** result, int max_depth,
- int skip_count, const void *uc) {
- return not_implemented();
-}
-
-
-#endif // BASE_STACKTRACE_WIN32_INL_H_
diff --git a/src/third_party/gperftools-2.5/src/stacktrace_x86-inl.h b/src/third_party/gperftools-2.5/src/stacktrace_x86-inl.h
deleted file mode 100644
index 46eb5d82d71..00000000000
--- a/src/third_party/gperftools-2.5/src/stacktrace_x86-inl.h
+++ /dev/null
@@ -1,354 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-//
-// Produce stack trace
-
-#ifndef BASE_STACKTRACE_X86_INL_H_
-#define BASE_STACKTRACE_X86_INL_H_
-// Note: this file is included into stacktrace.cc more than once.
-// Anything that should only be defined once should be here:
-
-#include "config.h"
-#include <stdlib.h> // for NULL
-#include <assert.h>
-#if defined(HAVE_SYS_UCONTEXT_H)
-#include <sys/ucontext.h>
-#elif defined(HAVE_UCONTEXT_H)
-#include <ucontext.h> // for ucontext_t
-#elif defined(HAVE_CYGWIN_SIGNAL_H)
-// cygwin/signal.h has a buglet where it uses pthread_attr_t without
-// #including <pthread.h> itself. So we have to do it.
-# ifdef HAVE_PTHREAD
-# include <pthread.h>
-# endif
-#include <cygwin/signal.h>
-typedef ucontext ucontext_t;
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h> // for uintptr_t
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h> // for msync
-#include "base/vdso_support.h"
-#endif
-
-#include "gperftools/stacktrace.h"
-
-#if defined(__linux__) && defined(__i386__) && defined(__ELF__) && defined(HAVE_MMAP)
-// Count "push %reg" instructions in VDSO __kernel_vsyscall(),
-// preceding "syscall" or "sysenter".
-// If __kernel_vsyscall uses frame pointer, answer 0.
-//
-// kMaxBytes tells how many instruction bytes of __kernel_vsyscall
-// to analyze before giving up. Up to kMaxBytes+1 bytes of
-// instructions could be accessed.
-//
-// Here are known __kernel_vsyscall instruction sequences:
-//
-// SYSENTER (linux-2.6.26/arch/x86/vdso/vdso32/sysenter.S).
-// Used on Intel.
-// 0xffffe400 <__kernel_vsyscall+0>: push %ecx
-// 0xffffe401 <__kernel_vsyscall+1>: push %edx
-// 0xffffe402 <__kernel_vsyscall+2>: push %ebp
-// 0xffffe403 <__kernel_vsyscall+3>: mov %esp,%ebp
-// 0xffffe405 <__kernel_vsyscall+5>: sysenter
-//
-// SYSCALL (see linux-2.6.26/arch/x86/vdso/vdso32/syscall.S).
-// Used on AMD.
-// 0xffffe400 <__kernel_vsyscall+0>: push %ebp
-// 0xffffe401 <__kernel_vsyscall+1>: mov %ecx,%ebp
-// 0xffffe403 <__kernel_vsyscall+3>: syscall
-//
-// i386 (see linux-2.6.26/arch/x86/vdso/vdso32/int80.S)
-// 0xffffe400 <__kernel_vsyscall+0>: int $0x80
-// 0xffffe401 <__kernel_vsyscall+1>: ret
-//
-static const int kMaxBytes = 10;
-
-// We use assert()s instead of DCHECK()s -- this is too low level
-// for DCHECK().
-
-static int CountPushInstructions(const unsigned char *const addr) {
- int result = 0;
- for (int i = 0; i < kMaxBytes; ++i) {
- if (addr[i] == 0x89) {
- // "mov reg,reg"
- if (addr[i + 1] == 0xE5) {
- // Found "mov %esp,%ebp".
- return 0;
- }
- ++i; // Skip register encoding byte.
- } else if (addr[i] == 0x0F &&
- (addr[i + 1] == 0x34 || addr[i + 1] == 0x05)) {
- // Found "sysenter" or "syscall".
- return result;
- } else if ((addr[i] & 0xF0) == 0x50) {
- // Found "push %reg".
- ++result;
- } else if (addr[i] == 0xCD && addr[i + 1] == 0x80) {
- // Found "int $0x80"
- assert(result == 0);
- return 0;
- } else {
- // Unexpected instruction.
- assert(0 == "unexpected instruction in __kernel_vsyscall");
- return 0;
- }
- }
- // Unexpected: didn't find SYSENTER or SYSCALL in
- // [__kernel_vsyscall, __kernel_vsyscall + kMaxBytes) interval.
- assert(0 == "did not find SYSENTER or SYSCALL in __kernel_vsyscall");
- return 0;
-}
-#endif
-
-// Given a pointer to a stack frame, locate and return the calling
-// stackframe, or return NULL if no stackframe can be found. Perform sanity
-// checks (the strictness of which is controlled by the boolean parameter
-// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
-template<bool STRICT_UNWINDING, bool WITH_CONTEXT>
-static void **NextStackFrame(void **old_sp, const void *uc) {
- void **new_sp = (void **) *old_sp;
-
-#if defined(__linux__) && defined(__i386__) && defined(HAVE_VDSO_SUPPORT)
- if (WITH_CONTEXT && uc != NULL) {
- // How many "push %reg" instructions are there at __kernel_vsyscall?
- // This is constant for a given kernel and processor, so compute
- // it only once.
- static int num_push_instructions = -1; // Sentinel: not computed yet.
- // Initialize with sentinel value: __kernel_rt_sigreturn can not possibly
- // be there.
- static const unsigned char *kernel_rt_sigreturn_address = NULL;
- static const unsigned char *kernel_vsyscall_address = NULL;
- if (num_push_instructions == -1) {
- base::VDSOSupport vdso;
- if (vdso.IsPresent()) {
- base::VDSOSupport::SymbolInfo rt_sigreturn_symbol_info;
- base::VDSOSupport::SymbolInfo vsyscall_symbol_info;
- if (!vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.5",
- STT_FUNC, &rt_sigreturn_symbol_info) ||
- !vdso.LookupSymbol("__kernel_vsyscall", "LINUX_2.5",
- STT_FUNC, &vsyscall_symbol_info) ||
- rt_sigreturn_symbol_info.address == NULL ||
- vsyscall_symbol_info.address == NULL) {
- // Unexpected: 32-bit VDSO is present, yet one of the expected
- // symbols is missing or NULL.
- assert(0 == "VDSO is present, but doesn't have expected symbols");
- num_push_instructions = 0;
- } else {
- kernel_rt_sigreturn_address =
- reinterpret_cast<const unsigned char *>(
- rt_sigreturn_symbol_info.address);
- kernel_vsyscall_address =
- reinterpret_cast<const unsigned char *>(
- vsyscall_symbol_info.address);
- num_push_instructions =
- CountPushInstructions(kernel_vsyscall_address);
- }
- } else {
- num_push_instructions = 0;
- }
- }
- if (num_push_instructions != 0 && kernel_rt_sigreturn_address != NULL &&
- old_sp[1] == kernel_rt_sigreturn_address) {
- const ucontext_t *ucv = static_cast<const ucontext_t *>(uc);
- // This kernel does not use frame pointer in its VDSO code,
- // and so %ebp is not suitable for unwinding.
- void **const reg_ebp =
- reinterpret_cast<void **>(ucv->uc_mcontext.gregs[REG_EBP]);
- const unsigned char *const reg_eip =
- reinterpret_cast<unsigned char *>(ucv->uc_mcontext.gregs[REG_EIP]);
- if (new_sp == reg_ebp &&
- kernel_vsyscall_address <= reg_eip &&
- reg_eip - kernel_vsyscall_address < kMaxBytes) {
- // We "stepped up" to __kernel_vsyscall, but %ebp is not usable.
- // Restore from 'ucv' instead.
- void **const reg_esp =
- reinterpret_cast<void **>(ucv->uc_mcontext.gregs[REG_ESP]);
- // Check that alleged %esp is not NULL and is reasonably aligned.
- if (reg_esp &&
- ((uintptr_t)reg_esp & (sizeof(reg_esp) - 1)) == 0) {
- // Check that alleged %esp is actually readable. This is to prevent
- // "double fault" in case we hit the first fault due to e.g. stack
- // corruption.
- //
- // page_size is linker-initalized to avoid async-unsafe locking
- // that GCC would otherwise insert (__cxa_guard_acquire etc).
- static int page_size;
- if (page_size == 0) {
- // First time through.
- page_size = getpagesize();
- }
- void *const reg_esp_aligned =
- reinterpret_cast<void *>(
- (uintptr_t)(reg_esp + num_push_instructions - 1) &
- ~(page_size - 1));
- if (msync(reg_esp_aligned, page_size, MS_ASYNC) == 0) {
- // Alleged %esp is readable, use it for further unwinding.
- new_sp = reinterpret_cast<void **>(
- reg_esp[num_push_instructions - 1]);
- }
- }
- }
- }
- }
-#endif
-
- // Check that the transition from frame pointer old_sp to frame
- // pointer new_sp isn't clearly bogus
- if (STRICT_UNWINDING) {
- // With the stack growing downwards, older stack frame must be
- // at a greater address that the current one.
- if (new_sp <= old_sp) return NULL;
- // Assume stack frames larger than 100,000 bytes are bogus.
- if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
- } else {
- // In the non-strict mode, allow discontiguous stack frames.
- // (alternate-signal-stacks for example).
- if (new_sp == old_sp) return NULL;
- if (new_sp > old_sp) {
- // And allow frames upto about 1MB.
- const uintptr_t delta = (uintptr_t)new_sp - (uintptr_t)old_sp;
- const uintptr_t acceptable_delta = 1000000;
- if (delta > acceptable_delta) {
- return NULL;
- }
- }
- }
- if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
-#ifdef __i386__
- // On 64-bit machines, the stack pointer can be very close to
- // 0xffffffff, so we explicitly check for a pointer into the
- // last two pages in the address space
- if ((uintptr_t)new_sp >= 0xffffe000) return NULL;
-#endif
-#ifdef HAVE_MMAP
- if (!STRICT_UNWINDING) {
- // Lax sanity checks cause a crash on AMD-based machines with
- // VDSO-enabled kernels.
- // Make an extra sanity check to insure new_sp is readable.
- // Note: NextStackFrame<false>() is only called while the program
- // is already on its last leg, so it's ok to be slow here.
- static int page_size = getpagesize();
- void *new_sp_aligned = (void *)((uintptr_t)new_sp & ~(page_size - 1));
- if (msync(new_sp_aligned, page_size, MS_ASYNC) == -1)
- return NULL;
- }
-#endif
- return new_sp;
-}
-
-#endif // BASE_STACKTRACE_X86_INL_H_
-
-// Note: this part of the file is included several times.
-// Do not put globals below.
-
-// The following 4 functions are generated from the code below:
-// GetStack{Trace,Frames}()
-// GetStack{Trace,Frames}WithContext()
-//
-// These functions take the following args:
-// void** result: the stack-trace, as an array
-// int* sizes: the size of each stack frame, as an array
-// (GetStackFrames* only)
-// int max_depth: the size of the result (and sizes) array(s)
-// int skip_count: how many stack pointers to skip before storing in result
-// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
-
-static int GET_STACK_TRACE_OR_FRAMES {
- void **sp;
-#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __llvm__
- // __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8.
- // It's always correct on llvm, and the techniques below aren't (in
- // particular, llvm-gcc will make a copy of pcs, so it's not in sp[2]),
- // so we also prefer __builtin_frame_address when running under llvm.
- sp = reinterpret_cast<void**>(__builtin_frame_address(0));
-#elif defined(__i386__)
- // Stack frame format:
- // sp[0] pointer to previous frame
- // sp[1] caller address
- // sp[2] first argument
- // ...
- // NOTE: This will break under llvm, since result is a copy and not in sp[2]
- sp = (void **)&result - 2;
-#elif defined(__x86_64__)
- unsigned long rbp;
- // Move the value of the register %rbp into the local variable rbp.
- // We need 'volatile' to prevent this instruction from getting moved
- // around during optimization to before function prologue is done.
- // An alternative way to achieve this
- // would be (before this __asm__ instruction) to call Noop() defined as
- // static void Noop() __attribute__ ((noinline)); // prevent inlining
- // static void Noop() { asm(""); } // prevent optimizing-away
- __asm__ volatile ("mov %%rbp, %0" : "=r" (rbp));
- // Arguments are passed in registers on x86-64, so we can't just
- // offset from &result
- sp = (void **) rbp;
-#else
-# error Using stacktrace_x86-inl.h on a non x86 architecture!
-#endif
-
- skip_count++; // skip parent's frame due to indirection in stacktrace.cc
-
- int n = 0;
- while (sp && n < max_depth) {
- if (*(sp+1) == reinterpret_cast<void *>(0)) {
- // In 64-bit code, we often see a frame that
- // points to itself and has a return address of 0.
- break;
- }
-#if !IS_WITH_CONTEXT
- const void *const ucp = NULL;
-#endif
- void **next_sp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(sp, ucp);
- if (skip_count > 0) {
- skip_count--;
- } else {
- result[n] = *(sp+1);
-#if IS_STACK_FRAMES
- if (next_sp > sp) {
- sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp;
- } else {
- // A frame-size of 0 is used to indicate unknown frame size.
- sizes[n] = 0;
- }
-#endif
- n++;
- }
- sp = next_sp;
- }
- return n;
-}
diff --git a/src/third_party/gperftools-2.5/src/static_vars.cc b/src/third_party/gperftools-2.5/src/static_vars.cc
deleted file mode 100644
index 47bdce14d60..00000000000
--- a/src/third_party/gperftools-2.5/src/static_vars.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Ken Ashcraft <opensource@google.com>
-
-#include <config.h>
-#include "static_vars.h"
-#include <stddef.h> // for NULL
-#include <new> // for operator new
-#ifdef HAVE_PTHREAD
-#include <pthread.h> // for pthread_atfork
-#endif
-#include "internal_logging.h" // for CHECK_CONDITION
-#include "common.h"
-#include "sampler.h" // for Sampler
-#include "getenv_safe.h" // TCMallocGetenvSafe
-#include "base/googleinit.h"
-#include "maybe_threads.h"
-
-namespace tcmalloc {
-
-#if defined(HAVE_FORK) && defined(HAVE_PTHREAD)
-// These following two functions are registered via pthread_atfork to make
-// sure the central_cache locks remain in a consisten state in the forked
-// version of the thread.
-
-void CentralCacheLockAll()
-{
- Static::pageheap_lock()->Lock();
- for (int i = 0; i < kNumClasses; ++i)
- Static::central_cache()[i].Lock();
-}
-
-void CentralCacheUnlockAll()
-{
- for (int i = 0; i < kNumClasses; ++i)
- Static::central_cache()[i].Unlock();
- Static::pageheap_lock()->Unlock();
-}
-#endif
-
-SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED);
-SizeMap Static::sizemap_;
-CentralFreeListPadded Static::central_cache_[kNumClasses];
-PageHeapAllocator<Span> Static::span_allocator_;
-PageHeapAllocator<StackTrace> Static::stacktrace_allocator_;
-Span Static::sampled_objects_;
-PageHeapAllocator<StackTraceTable::Bucket> Static::bucket_allocator_;
-StackTrace* Static::growth_stacks_ = NULL;
-PageHeap* Static::pageheap_ = NULL;
-
-
-void Static::InitStaticVars() {
- sizemap_.Init();
- span_allocator_.Init();
- span_allocator_.New(); // Reduce cache conflicts
- span_allocator_.New(); // Reduce cache conflicts
- stacktrace_allocator_.Init();
- bucket_allocator_.Init();
- // Do a bit of sanitizing: make sure central_cache is aligned properly
- CHECK_CONDITION((sizeof(central_cache_[0]) % 64) == 0);
- for (int i = 0; i < kNumClasses; ++i) {
- central_cache_[i].Init(i);
- }
-
- // It's important to have PageHeap allocated, not in static storage,
- // so that HeapLeakChecker does not consider all the byte patterns stored
- // in is caches as pointers that are sources of heap object liveness,
- // which leads to it missing some memory leaks.
- pageheap_ = new (MetaDataAlloc(sizeof(PageHeap))) PageHeap;
-
- bool aggressive_decommit =
- tcmalloc::commandlineflags::StringToBool(
- TCMallocGetenvSafe("TCMALLOC_AGGRESSIVE_DECOMMIT"), false);
-
- pageheap_->SetAggressiveDecommit(aggressive_decommit);
-
- DLL_Init(&sampled_objects_);
- Sampler::InitStatics();
-}
-
-
-#if defined(HAVE_FORK) && defined(HAVE_PTHREAD) && !defined(__APPLE__)
-
-static inline
-void SetupAtForkLocksHandler()
-{
- perftools_pthread_atfork(
- CentralCacheLockAll, // parent calls before fork
- CentralCacheUnlockAll, // parent calls after fork
- CentralCacheUnlockAll); // child calls after fork
-}
-REGISTER_MODULE_INITIALIZER(tcmalloc_fork_handler, SetupAtForkLocksHandler());
-
-#endif
-
-} // namespace tcmalloc
diff --git a/src/third_party/gperftools-2.5/src/static_vars.h b/src/third_party/gperftools-2.5/src/static_vars.h
deleted file mode 100644
index c662e40cd73..00000000000
--- a/src/third_party/gperftools-2.5/src/static_vars.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Ken Ashcraft <opensource@google.com>
-//
-// Static variables shared by multiple classes.
-
-#ifndef TCMALLOC_STATIC_VARS_H_
-#define TCMALLOC_STATIC_VARS_H_
-
-#include <config.h>
-#include "base/spinlock.h"
-#include "central_freelist.h"
-#include "common.h"
-#include "page_heap.h"
-#include "page_heap_allocator.h"
-#include "span.h"
-#include "stack_trace_table.h"
-
-namespace tcmalloc {
-
-class Static {
- public:
- // Linker initialized, so this lock can be accessed at any time.
- static SpinLock* pageheap_lock() { return &pageheap_lock_; }
-
- // Must be called before calling any of the accessors below.
- static void InitStaticVars();
-
- // Central cache -- an array of free-lists, one per size-class.
- // We have a separate lock per free-list to reduce contention.
- static CentralFreeListPadded* central_cache() { return central_cache_; }
-
- static SizeMap* sizemap() { return &sizemap_; }
-
- //////////////////////////////////////////////////////////////////////
- // In addition to the explicit initialization comment, the variables below
- // must be protected by pageheap_lock.
-
- // Page-level allocator.
- static PageHeap* pageheap() { return pageheap_; }
-
- static PageHeapAllocator<Span>* span_allocator() { return &span_allocator_; }
-
- static PageHeapAllocator<StackTrace>* stacktrace_allocator() {
- return &stacktrace_allocator_;
- }
-
- static StackTrace* growth_stacks() { return growth_stacks_; }
- static void set_growth_stacks(StackTrace* s) { growth_stacks_ = s; }
-
- // State kept for sampled allocations (/pprof/heap support)
- static Span* sampled_objects() { return &sampled_objects_; }
- static PageHeapAllocator<StackTraceTable::Bucket>* bucket_allocator() {
- return &bucket_allocator_;
- }
-
- // Check if InitStaticVars() has been run.
- static bool IsInited() { return pageheap() != NULL; }
-
- private:
- static SpinLock pageheap_lock_;
-
- // These static variables require explicit initialization. We cannot
- // count on their constructors to do any initialization because other
- // static variables may try to allocate memory before these variables
- // can run their constructors.
-
- static SizeMap sizemap_;
- static CentralFreeListPadded central_cache_[kNumClasses];
- static PageHeapAllocator<Span> span_allocator_;
- static PageHeapAllocator<StackTrace> stacktrace_allocator_;
- static Span sampled_objects_;
- static PageHeapAllocator<StackTraceTable::Bucket> bucket_allocator_;
-
- // Linked list of stack traces recorded every time we allocated memory
- // from the system. Useful for finding allocation sites that cause
- // increase in the footprint of the system. The linked list pointer
- // is stored in trace->stack[kMaxStackDepth-1].
- static StackTrace* growth_stacks_;
-
- static PageHeap* pageheap_;
-};
-
-} // namespace tcmalloc
-
-#endif // TCMALLOC_STATIC_VARS_H_
diff --git a/src/third_party/gperftools-2.5/src/symbolize.cc b/src/third_party/gperftools-2.5/src/symbolize.cc
deleted file mode 100755
index a27106e8bce..00000000000
--- a/src/third_party/gperftools-2.5/src/symbolize.cc
+++ /dev/null
@@ -1,285 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2009, 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
-//
-// This forks out to pprof to do the actual symbolizing. We might
-// be better off writing our own in C++.
-
-#include "config.h"
-#include "symbolize.h"
-#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for write()
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h> // for socketpair() -- needed by Symbolize
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h> // for wait() -- needed by Symbolize
-#endif
-#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/logging.h"
-#include "base/sysinfo.h"
-
-using std::string;
-using tcmalloc::DumpProcSelfMaps; // from sysinfo.h
-
-
-DEFINE_string(symbolize_pprof,
- EnvToString("PPROF_PATH", "pprof"),
- "Path to pprof to call for reporting function names.");
-
-// heap_profile_table_pprof may be referenced after destructors are
-// called (since that's when leak-checking is done), so we make
-// 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 const char* GetProgramInvocationName() {
-#if defined(HAVE_PROGRAM_INVOCATION_NAME)
-#ifdef __UCLIBC__
- extern const char* program_invocation_name; // uclibc provides this
-#else
- extern char* program_invocation_name; // gcc provides this
-#endif
- 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
-}
-
-// Prints an error message when you can't run Symbolize().
-static void PrintError(const char* reason) {
- RAW_LOG(ERROR,
- "*** WARNING: Cannot convert addresses to symbols in output below.\n"
- "*** Reason: %s\n"
- "*** If you cannot fix this, try running pprof directly.\n",
- reason);
-}
-
-void SymbolTable::Add(const void* addr) {
- symbolization_table_[addr] = "";
-}
-
-const char* SymbolTable::GetSymbol(const void* addr) {
- return symbolization_table_[addr];
-}
-
-// Updates symbolization_table with the pointers to symbol names corresponding
-// to its keys. The symbol names are stored in out, which is allocated and
-// freed by the caller of this routine.
-// Note that the forking/etc is not thread-safe or re-entrant. That's
-// ok for the purpose we need -- reporting leaks detected by heap-checker
-// -- but be careful if you decide to use this routine for other purposes.
-// Returns number of symbols read on error. If can't symbolize, returns 0
-// and emits an error message about why.
-int SymbolTable::Symbolize() {
-#if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS_WAIT_H)
- PrintError("Perftools does not know how to call a sub-process on this O/S");
- return 0;
-#else
- const char* argv0 = GetProgramInvocationName();
- if (argv0 == NULL) { // can't call symbolize if we can't figure out our name
- PrintError("Cannot figure out the name of this executable (argv0)");
- return 0;
- }
- if (access(g_pprof_path->c_str(), R_OK) != 0) {
- PrintError("Cannot find 'pprof' (is PPROF_PATH set correctly?)");
- return 0;
- }
-
- // All this work is to do two-way communication. ugh.
- 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
-
- // The client program may close its stdin and/or stdout and/or stderr
- // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
- // In this case the communication between the forked processes may be broken
- // if either the parent or the child tries to close or duplicate these
- // descriptors. The loop below produces two pairs of file descriptors, each
- // greater than 2 (stderr).
- for (int i = 0; i < 5; i++) {
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_fds[i]) == -1) {
- for (int j = 0; j < i; j++) {
- close(child_fds[j][0]);
- close(child_fds[j][1]);
- PrintError("Cannot create a socket pair");
- }
- return 0;
- } else {
- if ((child_fds[i][0] > 2) && (child_fds[i][1] > 2)) {
- if (child_in == NULL) {
- child_in = child_fds[i];
- } else {
- child_out = child_fds[i];
- for (int j = 0; j < i; j++) {
- if (child_fds[j] == child_in) continue;
- close(child_fds[j][0]);
- close(child_fds[j][1]);
- }
- break;
- }
- }
- }
- }
-
- switch (fork()) {
- case -1: { // error
- close(child_in[0]);
- close(child_in[1]);
- close(child_out[0]);
- close(child_out[1]);
- PrintError("Unknown error calling fork()");
- return 0;
- }
- case 0: { // child
- close(child_in[1]); // child uses the 0's, parent uses the 1's
- close(child_out[1]); // child uses the 0's, parent uses the 1's
- close(0);
- close(1);
- if (dup2(child_in[0], 0) == -1) _exit(1);
- if (dup2(child_out[0], 1) == -1) _exit(2);
- // Unset vars that might cause trouble when we fork
- unsetenv("CPUPROFILE");
- unsetenv("HEAPPROFILE");
- unsetenv("HEAPCHECK");
- unsetenv("PERFTOOLS_VERBOSE");
- execlp(g_pprof_path->c_str(), g_pprof_path->c_str(),
- "--symbols", argv0, NULL);
- _exit(3); // if execvp fails, it's bad news for us
- }
- default: { // parent
- close(child_in[0]); // child uses the 0's, parent uses the 1's
- close(child_out[0]); // child uses the 0's, parent uses the 1's
-#ifdef HAVE_POLL_H
- // Waiting for 1ms seems to give the OS time to notice any errors.
- poll(0, 0, 1);
- // For maximum safety, we check to make sure the execlp
- // succeeded before trying to write. (Otherwise we'll get a
- // SIGPIPE.) For systems without poll.h, we'll just skip this
- // check, and trust that the user set PPROF_PATH correctly!
- struct pollfd pfd = { child_in[1], POLLOUT, 0 };
- if (!poll(&pfd, 1, 0) || !(pfd.revents & POLLOUT) ||
- (pfd.revents & (POLLHUP|POLLERR))) {
- PrintError("Cannot run 'pprof' (is PPROF_PATH set correctly?)");
- 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.
- const int kOutBufSize = 24 * symbolization_table_.size();
- char *pprof_buffer = new char[kOutBufSize];
- int written = 0;
- for (SymbolMap::const_iterator iter = symbolization_table_.begin();
- iter != symbolization_table_.end(); ++iter) {
- written += snprintf(pprof_buffer + written, kOutBufSize - written,
- // pprof expects format to be 0xXXXXXX
- "0x%" PRIxPTR "\n", reinterpret_cast<uintptr_t>(iter->first));
- }
- write(child_in[1], pprof_buffer, strlen(pprof_buffer));
- close(child_in[1]); // that's all we need to write
-
- const int kSymbolBufferSize = kSymbolSize * symbolization_table_.size();
- int total_bytes_read = 0;
- delete[] symbol_buffer_;
- symbol_buffer_ = new char[kSymbolBufferSize];
- memset(symbol_buffer_, '\0', kSymbolBufferSize);
- while (1) {
- int bytes_read = read(child_out[1], symbol_buffer_ + total_bytes_read,
- kSymbolBufferSize - total_bytes_read);
- if (bytes_read < 0) {
- close(child_out[1]);
- PrintError("Cannot read data from pprof");
- return 0;
- } else if (bytes_read == 0) {
- close(child_out[1]);
- wait(NULL);
- break;
- } else {
- total_bytes_read += bytes_read;
- }
- }
- // We have successfully read the output of pprof into out. Make sure
- // the last symbol is full (we can tell because it ends with a \n).
- if (total_bytes_read == 0 || symbol_buffer_[total_bytes_read - 1] != '\n')
- return 0;
- // make the symbolization_table_ values point to the output vector
- SymbolMap::iterator fill = symbolization_table_.begin();
- int num_symbols = 0;
- const char *current_name = symbol_buffer_;
- for (int i = 0; i < total_bytes_read; i++) {
- if (symbol_buffer_[i] == '\n') {
- fill->second = current_name;
- symbol_buffer_[i] = '\0';
- current_name = symbol_buffer_ + i + 1;
- fill++;
- num_symbols++;
- }
- }
- return num_symbols;
- }
- }
- PrintError("Unkown error (should never occur!)");
- return 0; // shouldn't be reachable
-#endif
-}
diff --git a/src/third_party/gperftools-2.5/src/symbolize.h b/src/third_party/gperftools-2.5/src/symbolize.h
deleted file mode 100644
index 728d073308a..00000000000
--- a/src/third_party/gperftools-2.5/src/symbolize.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2009, 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
-
-#ifndef TCMALLOC_SYMBOLIZE_H_
-#define TCMALLOC_SYMBOLIZE_H_
-
-#include "config.h"
-#ifdef HAVE_STDINT_H
-#include <stdint.h> // for uintptr_t
-#endif
-#include <stddef.h> // for NULL
-#include <map>
-
-using std::map;
-
-// SymbolTable encapsulates the address operations necessary for stack trace
-// symbolization. A common use-case is to Add() the addresses from one or
-// several stack traces to a table, call Symbolize() once and use GetSymbol()
-// to get the symbol names for pretty-printing the stack traces.
-class SymbolTable {
- public:
- SymbolTable()
- : symbol_buffer_(NULL) {}
- ~SymbolTable() {
- delete[] symbol_buffer_;
- }
-
- // Adds an address to the table. This may overwrite a currently known symbol
- // name, so Add() should not generally be called after Symbolize().
- void Add(const void* addr);
-
- // Returns the symbol name for addr, if the given address was added before
- // the last successful call to Symbolize(). Otherwise may return an empty
- // c-string.
- const char* GetSymbol(const void* addr);
-
- // Obtains the symbol names for the addresses stored in the table and returns
- // the number of addresses actually symbolized.
- int Symbolize();
-
- private:
- typedef map<const void*, const char*> SymbolMap;
-
- // An average size of memory allocated for a stack trace symbol.
- static const int kSymbolSize = 1024;
-
- // Map from addresses to symbol names.
- SymbolMap symbolization_table_;
-
- // Pointer to the buffer that stores the symbol names.
- char *symbol_buffer_;
-};
-
-#endif // TCMALLOC_SYMBOLIZE_H_
diff --git a/src/third_party/gperftools-2.5/src/system-alloc.cc b/src/third_party/gperftools-2.5/src/system-alloc.cc
deleted file mode 100755
index 084009c89f7..00000000000
--- a/src/third_party/gperftools-2.5/src/system-alloc.cc
+++ /dev/null
@@ -1,562 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-
-#include <config.h>
-#include <errno.h> // for EAGAIN, errno
-#include <fcntl.h> // for open, O_RDWR
-#include <stddef.h> // for size_t, NULL, ptrdiff_t
-#if defined HAVE_STDINT_H
-#include <stdint.h> // for uintptr_t, intptr_t
-#elif defined HAVE_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <sys/types.h>
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h> // for munmap, mmap, MADV_DONTNEED, etc
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for sbrk, getpagesize, off_t
-#endif
-#include <new> // for operator new
-#include <gperftools/malloc_extension.h>
-#include "base/basictypes.h"
-#include "base/commandlineflags.h"
-#include "base/spinlock.h" // for SpinLockHolder, SpinLock, etc
-#include "common.h"
-#include "internal_logging.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
-
-// Linux added support for MADV_FREE in 4.5 but we aren't ready to use it
-// yet. Among other things, using compile-time detection leads to poor
-// results when compiling on a system with MADV_FREE and running on a
-// system without it. See https://github.com/gperftools/gperftools/issues/780.
-#if defined(__linux__) && defined(MADV_FREE) && !defined(TCMALLOC_USE_MADV_FREE)
-# undef MADV_FREE
-#endif
-
-// MADV_FREE is specifically designed for use by malloc(), but only
-// FreeBSD supports it; in linux we fall back to the somewhat inferior
-// MADV_DONTNEED.
-#if !defined(MADV_FREE) && defined(MADV_DONTNEED)
-# define MADV_FREE MADV_DONTNEED
-#endif
-
-// Solaris has a bug where it doesn't declare madvise() for C++.
-// http://www.opensolaris.org/jive/thread.jspa?threadID=21035&tstart=0
-#if defined(__sun) && defined(__SVR4)
-# include <sys/types.h> // for caddr_t
- extern "C" { extern int madvise(caddr_t, size_t, int); }
-#endif
-
-// Set kDebugMode mode so that we can have use C++ conditionals
-// instead of preprocessor conditionals.
-#ifdef NDEBUG
-static const bool kDebugMode = false;
-#else
-static const bool kDebugMode = true;
-#endif
-
-// TODO(sanjay): Move the code below into the tcmalloc namespace
-using tcmalloc::kLog;
-using tcmalloc::Log;
-
-// Anonymous namespace to avoid name conflicts on "CheckAddressBits".
-namespace {
-
-// Check that no bit is set at position ADDRESS_BITS or higher.
-template <int ADDRESS_BITS> bool CheckAddressBits(uintptr_t ptr) {
- return (ptr >> ADDRESS_BITS) == 0;
-}
-
-// Specialize for the bit width of a pointer to avoid undefined shift.
-template <> bool CheckAddressBits<8 * sizeof(void*)>(uintptr_t ptr) {
- return true;
-}
-
-} // Anonymous namespace to avoid name conflicts on "CheckAddressBits".
-
-COMPILE_ASSERT(kAddressBits <= 8 * sizeof(void*),
- address_bits_larger_than_pointer_size);
-
-static SpinLock spinlock(SpinLock::LINKER_INITIALIZED);
-
-#if defined(HAVE_MMAP) || defined(MADV_FREE)
-// Page size is initialized on demand (only needed for mmap-based allocators)
-static size_t pagesize = 0;
-#endif
-
-// The current system allocator
-SysAllocator* sys_alloc = NULL;
-
-// Number of bytes taken from system.
-size_t TCMalloc_SystemTaken = 0;
-
-// Configuration parameters.
-DEFINE_int32(malloc_devmem_start,
- EnvToInt("TCMALLOC_DEVMEM_START", 0),
- "Physical memory starting location in MB for /dev/mem allocation."
- " Setting this to 0 disables /dev/mem allocation");
-DEFINE_int32(malloc_devmem_limit,
- EnvToInt("TCMALLOC_DEVMEM_LIMIT", 0),
- "Physical memory limit location in MB for /dev/mem allocation."
- " Setting this to 0 means no limit.");
-DEFINE_bool(malloc_skip_sbrk,
- EnvToBool("TCMALLOC_SKIP_SBRK", false),
- "Whether sbrk can be used to obtain memory.");
-DEFINE_bool(malloc_skip_mmap,
- EnvToBool("TCMALLOC_SKIP_MMAP", false),
- "Whether mmap can be used to obtain memory.");
-DEFINE_bool(malloc_disable_memory_release,
- EnvToBool("TCMALLOC_DISABLE_MEMORY_RELEASE", false),
- "Whether MADV_FREE/MADV_DONTNEED should be used"
- " to return unused memory to the system.");
-
-// static allocators
-class SbrkSysAllocator : public SysAllocator {
-public:
- SbrkSysAllocator() : SysAllocator() {
- }
- void* Alloc(size_t size, size_t *actual_size, size_t alignment);
-};
-static union {
- char buf[sizeof(SbrkSysAllocator)];
- void *ptr;
-} sbrk_space;
-
-class MmapSysAllocator : public SysAllocator {
-public:
- MmapSysAllocator() : SysAllocator() {
- }
- void* Alloc(size_t size, size_t *actual_size, size_t alignment);
-};
-static union {
- char buf[sizeof(MmapSysAllocator)];
- void *ptr;
-} mmap_space;
-
-class DevMemSysAllocator : public SysAllocator {
-public:
- DevMemSysAllocator() : SysAllocator() {
- }
- void* Alloc(size_t size, size_t *actual_size, size_t alignment);
-};
-
-class DefaultSysAllocator : public SysAllocator {
- public:
- DefaultSysAllocator() : SysAllocator() {
- for (int i = 0; i < kMaxAllocators; i++) {
- failed_[i] = true;
- allocs_[i] = NULL;
- names_[i] = NULL;
- }
- }
- void SetChildAllocator(SysAllocator* alloc, unsigned int index,
- const char* name) {
- 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);
-
- private:
- static const int kMaxAllocators = 2;
- bool failed_[kMaxAllocators];
- SysAllocator* allocs_[kMaxAllocators];
- const char* names_[kMaxAllocators];
-};
-static union {
- char buf[sizeof(DefaultSysAllocator)];
- void *ptr;
-} default_space;
-static const char sbrk_name[] = "SbrkSysAllocator";
-static const char mmap_name[] = "MmapSysAllocator";
-
-
-void* SbrkSysAllocator::Alloc(size_t size, size_t *actual_size,
- size_t alignment) {
-#if !defined(HAVE_SBRK) || defined(__UCLIBC__)
- return NULL;
-#else
- // Check if we should use sbrk allocation.
- // FLAGS_malloc_skip_sbrk starts out as false (its uninitialized
- // state) and eventually gets initialized to the specified value. Note
- // that this code runs for a while before the flags are initialized.
- // That means that even if this flag is set to true, some (initial)
- // memory will be allocated with sbrk before the flag takes effect.
- if (FLAGS_malloc_skip_sbrk) {
- return NULL;
- }
-
- // sbrk will release memory if passed a negative number, so we do
- // a strict check here
- if (static_cast<ptrdiff_t>(size + alignment) < 0) return NULL;
-
- // This doesn't overflow because TCMalloc_SystemAlloc has already
- // tested for overflow at the alignment boundary.
- size = ((size + alignment - 1) / alignment) * alignment;
-
- // "actual_size" indicates that the bytes from the returned pointer
- // p up to and including (p + actual_size - 1) have been allocated.
- if (actual_size) {
- *actual_size = size;
- }
-
- // Check that we we're not asking for so much more memory that we'd
- // wrap around the end of the virtual address space. (This seems
- // like something sbrk() should check for us, and indeed opensolaris
- // does, but glibc does not:
- // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/sys/sbrk.c?a=true
- // http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/libc/misc/sbrk.c?rev=1.1.2.1&content-type=text/plain&cvsroot=glibc
- // Without this check, sbrk may succeed when it ought to fail.)
- if (reinterpret_cast<intptr_t>(sbrk(0)) + size < size) {
- return NULL;
- }
-
- void* result = sbrk(size);
- if (result == reinterpret_cast<void*>(-1)) {
- return NULL;
- }
-
- // Is it aligned?
- uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
- if ((ptr & (alignment-1)) == 0) return result;
-
- // Try to get more memory for alignment
- size_t extra = alignment - (ptr & (alignment-1));
- void* r2 = sbrk(extra);
- if (reinterpret_cast<uintptr_t>(r2) == (ptr + size)) {
- // Contiguous with previous result
- return reinterpret_cast<void*>(ptr + extra);
- }
-
- // Give up and ask for "size + alignment - 1" bytes so
- // that we can find an aligned region within it.
- result = sbrk(size + alignment - 1);
- if (result == reinterpret_cast<void*>(-1)) {
- return NULL;
- }
- ptr = reinterpret_cast<uintptr_t>(result);
- if ((ptr & (alignment-1)) != 0) {
- ptr += alignment - (ptr & (alignment-1));
- }
- return reinterpret_cast<void*>(ptr);
-#endif // HAVE_SBRK
-}
-
-void* MmapSysAllocator::Alloc(size_t size, size_t *actual_size,
- size_t alignment) {
-#ifndef HAVE_MMAP
- return NULL;
-#else
- // Check if we should use mmap allocation.
- // FLAGS_malloc_skip_mmap starts out as false (its uninitialized
- // state) and eventually gets initialized to the specified value. Note
- // that this code runs for a while before the flags are initialized.
- // Chances are we never get here before the flags are initialized since
- // sbrk is used until the heap is exhausted (before mmap is used).
- if (FLAGS_malloc_skip_mmap) {
- return NULL;
- }
-
- // Enforce page alignment
- if (pagesize == 0) pagesize = getpagesize();
- if (alignment < pagesize) alignment = pagesize;
- size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;
- if (aligned_size < size) {
- return NULL;
- }
- size = aligned_size;
-
- // "actual_size" indicates that the bytes from the returned pointer
- // p up to and including (p + actual_size - 1) have been allocated.
- if (actual_size) {
- *actual_size = size;
- }
-
- // Ask for extra memory if alignment > pagesize
- size_t extra = 0;
- if (alignment > pagesize) {
- extra = alignment - pagesize;
- }
-
- // Note: size + extra does not overflow since:
- // size + alignment < (1<<NBITS).
- // and extra <= alignment
- // therefore size + extra < (1<<NBITS)
- void* result = mmap(NULL, size + extra,
- PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS,
- -1, 0);
- if (result == reinterpret_cast<void*>(MAP_FAILED)) {
- return NULL;
- }
-
- // Adjust the return memory so it is aligned
- uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
- size_t adjust = 0;
- if ((ptr & (alignment - 1)) != 0) {
- adjust = alignment - (ptr & (alignment - 1));
- }
-
- // Return the unused memory to the system
- if (adjust > 0) {
- munmap(reinterpret_cast<void*>(ptr), adjust);
- }
- if (adjust < extra) {
- munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);
- }
-
- ptr += adjust;
- return reinterpret_cast<void*>(ptr);
-#endif // HAVE_MMAP
-}
-
-void* DevMemSysAllocator::Alloc(size_t size, size_t *actual_size,
- size_t alignment) {
-#ifndef HAVE_MMAP
- return NULL;
-#else
- static bool initialized = false;
- static off_t physmem_base; // next physical memory address to allocate
- static off_t physmem_limit; // maximum physical address allowed
- static int physmem_fd; // file descriptor for /dev/mem
-
- // Check if we should use /dev/mem allocation. Note that it may take
- // a while to get this flag initialized, so meanwhile we fall back to
- // the next allocator. (It looks like 7MB gets allocated before
- // this flag gets initialized -khr.)
- if (FLAGS_malloc_devmem_start == 0) {
- // NOTE: not a devmem_failure - we'd like TCMalloc_SystemAlloc to
- // try us again next time.
- return NULL;
- }
-
- if (!initialized) {
- physmem_fd = open("/dev/mem", O_RDWR);
- if (physmem_fd < 0) {
- return NULL;
- }
- physmem_base = FLAGS_malloc_devmem_start*1024LL*1024LL;
- physmem_limit = FLAGS_malloc_devmem_limit*1024LL*1024LL;
- initialized = true;
- }
-
- // Enforce page alignment
- if (pagesize == 0) pagesize = getpagesize();
- if (alignment < pagesize) alignment = pagesize;
- size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;
- if (aligned_size < size) {
- return NULL;
- }
- size = aligned_size;
-
- // "actual_size" indicates that the bytes from the returned pointer
- // p up to and including (p + actual_size - 1) have been allocated.
- if (actual_size) {
- *actual_size = size;
- }
-
- // Ask for extra memory if alignment > pagesize
- size_t extra = 0;
- if (alignment > pagesize) {
- extra = alignment - pagesize;
- }
-
- // check to see if we have any memory left
- if (physmem_limit != 0 &&
- ((size + extra) > (physmem_limit - physmem_base))) {
- return NULL;
- }
-
- // Note: size + extra does not overflow since:
- // size + alignment < (1<<NBITS).
- // and extra <= alignment
- // therefore size + extra < (1<<NBITS)
- void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
- MAP_SHARED, physmem_fd, physmem_base);
- if (result == reinterpret_cast<void*>(MAP_FAILED)) {
- return NULL;
- }
- uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
-
- // Adjust the return memory so it is aligned
- size_t adjust = 0;
- if ((ptr & (alignment - 1)) != 0) {
- adjust = alignment - (ptr & (alignment - 1));
- }
-
- // Return the unused virtual memory to the system
- if (adjust > 0) {
- munmap(reinterpret_cast<void*>(ptr), adjust);
- }
- if (adjust < extra) {
- munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);
- }
-
- ptr += adjust;
- physmem_base += adjust + size;
-
- return reinterpret_cast<void*>(ptr);
-#endif // HAVE_MMAP
-}
-
-void* DefaultSysAllocator::Alloc(size_t size, size_t *actual_size,
- size_t alignment) {
- for (int i = 0; i < kMaxAllocators; i++) {
- if (!failed_[i] && allocs_[i] != NULL) {
- void* result = allocs_[i]->Alloc(size, actual_size, alignment);
- if (result != NULL) {
- return result;
- }
- failed_[i] = true;
- }
- }
- // After both failed, reset "failed_" to false so that a single failed
- // allocation won't make the allocator never work again.
- for (int i = 0; i < kMaxAllocators; i++) {
- failed_[i] = false;
- }
- return NULL;
-}
-
-ATTRIBUTE_WEAK ATTRIBUTE_NOINLINE
-SysAllocator *tc_get_sysalloc_override(SysAllocator *def)
-{
- return def;
-}
-
-static bool system_alloc_inited = false;
-void InitSystemAllocators(void) {
- MmapSysAllocator *mmap = new (mmap_space.buf) MmapSysAllocator();
- SbrkSysAllocator *sbrk = new (sbrk_space.buf) SbrkSysAllocator();
-
- // In 64-bit debug mode, place the mmap allocator first since it
- // allocates pointers that do not fit in 32 bits and therefore gives
- // us better testing of code's 64-bit correctness. It also leads to
- // less false negatives in heap-checking code. (Numbers are less
- // likely to look like pointers and therefore the conservative gc in
- // the heap-checker is less likely to misinterpret a number as a
- // pointer).
- DefaultSysAllocator *sdef = new (default_space.buf) DefaultSysAllocator();
- if (kDebugMode && sizeof(void*) > 4) {
- sdef->SetChildAllocator(mmap, 0, mmap_name);
- sdef->SetChildAllocator(sbrk, 1, sbrk_name);
- } else {
- sdef->SetChildAllocator(sbrk, 0, sbrk_name);
- sdef->SetChildAllocator(mmap, 1, mmap_name);
- }
-
- sys_alloc = tc_get_sysalloc_override(sdef);
-}
-
-void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
- size_t alignment) {
- // Discard requests that overflow
- if (size + alignment < size) return NULL;
-
- SpinLockHolder lock_holder(&spinlock);
-
- if (!system_alloc_inited) {
- InitSystemAllocators();
- system_alloc_inited = true;
- }
-
- // Enforce minimum alignment
- if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner);
-
- size_t actual_size_storage;
- if (actual_size == NULL) {
- actual_size = &actual_size_storage;
- }
-
- void* result = sys_alloc->Alloc(size, actual_size, alignment);
- if (result != NULL) {
- CHECK_CONDITION(
- CheckAddressBits<kAddressBits>(
- reinterpret_cast<uintptr_t>(result) + *actual_size - 1));
- TCMalloc_SystemTaken += *actual_size;
- }
- return result;
-}
-
-bool TCMalloc_SystemRelease(void* start, size_t length) {
-#ifdef MADV_FREE
- if (FLAGS_malloc_devmem_start) {
- // It's not safe to use MADV_FREE/MADV_DONTNEED if we've been
- // mapping /dev/mem for heap memory.
- return false;
- }
- if (FLAGS_malloc_disable_memory_release) return false;
- if (pagesize == 0) pagesize = getpagesize();
- const size_t pagemask = pagesize - 1;
-
- size_t new_start = reinterpret_cast<size_t>(start);
- size_t end = new_start + length;
- size_t new_end = end;
-
- // Round up the starting address and round down the ending address
- // to be page aligned:
- new_start = (new_start + pagesize - 1) & ~pagemask;
- new_end = new_end & ~pagemask;
-
- ASSERT((new_start & pagemask) == 0);
- ASSERT((new_end & pagemask) == 0);
- ASSERT(new_start >= reinterpret_cast<size_t>(start));
- ASSERT(new_end <= end);
-
- if (new_end > new_start) {
- int result;
- do {
- result = madvise(reinterpret_cast<char*>(new_start),
- new_end - new_start, MADV_FREE);
- } while (result == -1 && errno == EAGAIN);
-
- return result != -1;
- }
-#endif
- return false;
-}
-
-void TCMalloc_SystemCommit(void* start, size_t length) {
- // Nothing to do here. TCMalloc_SystemRelease does not alter pages
- // such that they need to be re-committed before they can be used by the
- // application.
-}
diff --git a/src/third_party/gperftools-2.5/src/system-alloc.h b/src/third_party/gperftools-2.5/src/system-alloc.h
deleted file mode 100644
index 8233f96e5ff..00000000000
--- a/src/third_party/gperftools-2.5/src/system-alloc.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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
-//
-// Routine that uses sbrk/mmap to allocate memory from the system.
-// Useful for implementing malloc.
-
-#ifndef TCMALLOC_SYSTEM_ALLOC_H_
-#define TCMALLOC_SYSTEM_ALLOC_H_
-
-#include <config.h>
-#include <stddef.h> // for size_t
-
-class SysAllocator;
-
-// REQUIRES: "alignment" is a power of two or "0" to indicate default alignment
-//
-// Allocate and return "N" bytes of zeroed memory.
-//
-// If actual_bytes is NULL then the returned memory is exactly the
-// requested size. If actual bytes is non-NULL then the allocator
-// may optionally return more bytes than asked for (i.e. return an
-// entire "huge" page if a huge page allocator is in use).
-//
-// The returned pointer is a multiple of "alignment" if non-zero. The
-// returned pointer will always be aligned suitably for holding a
-// void*, double, or size_t. In addition, if this platform defines
-// CACHELINE_ALIGNED, the return pointer will always be cacheline
-// aligned.
-//
-// Returns NULL when out of memory.
-extern PERFTOOLS_DLL_DECL
-void* TCMalloc_SystemAlloc(size_t bytes, size_t *actual_bytes,
- size_t alignment = 0);
-
-// This call is a hint to the operating system that the pages
-// contained in the specified range of memory will not be used for a
-// while, and can be released for use by other processes or the OS.
-// Pages which are released in this way may be destroyed (zeroed) by
-// the OS. The benefit of this function is that it frees memory for
-// use by the system, the cost is that the pages are faulted back into
-// the address space next time they are touched, which can impact
-// performance. (Only pages fully covered by the memory region will
-// be released, partial pages will not.)
-//
-// Returns false if release failed or not supported.
-extern PERFTOOLS_DLL_DECL
-bool TCMalloc_SystemRelease(void* start, size_t length);
-
-// Called to ressurect memory which has been previously released
-// to the system via TCMalloc_SystemRelease. An attempt to
-// commit a page that is already committed does not cause this
-// function to fail.
-extern PERFTOOLS_DLL_DECL
-void TCMalloc_SystemCommit(void* start, size_t length);
-
-// The current system allocator.
-extern PERFTOOLS_DLL_DECL SysAllocator* sys_alloc;
-
-// Number of bytes taken from system.
-extern PERFTOOLS_DLL_DECL size_t TCMalloc_SystemTaken;
-
-#endif /* TCMALLOC_SYSTEM_ALLOC_H_ */
diff --git a/src/third_party/gperftools-2.5/src/tcmalloc.cc b/src/third_party/gperftools-2.5/src/tcmalloc.cc
deleted file mode 100644
index b573b4a9821..00000000000
--- a/src/third_party/gperftools-2.5/src/tcmalloc.cc
+++ /dev/null
@@ -1,1915 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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>
-//
-// A malloc that uses a per-thread cache to satisfy small malloc requests.
-// (The time for malloc/free of a small object drops from 300 ns to 50 ns.)
-//
-// See doc/tcmalloc.html for a high-level
-// description of how this malloc works.
-//
-// SYNCHRONIZATION
-// 1. The thread-specific lists are accessed without acquiring any locks.
-// This is safe because each such list is only accessed by one thread.
-// 2. We have a lock per central free-list, and hold it while manipulating
-// the central free list for a particular size.
-// 3. The central page allocator is protected by "pageheap_lock".
-// 4. The pagemap (which maps from page-number to descriptor),
-// can be read without holding any locks, and written while holding
-// the "pageheap_lock".
-// 5. To improve performance, a subset of the information one can get
-// from the pagemap is cached in a data structure, pagemap_cache_,
-// that atomically reads and writes its entries. This cache can be
-// read and written without locking.
-//
-// This multi-threaded access to the pagemap is safe for fairly
-// subtle reasons. We basically assume that when an object X is
-// allocated by thread A and deallocated by thread B, there must
-// have been appropriate synchronization in the handoff of object
-// X from thread A to thread B. The same logic applies to pagemap_cache_.
-//
-// THE PAGEID-TO-SIZECLASS CACHE
-// Hot PageID-to-sizeclass mappings are held by pagemap_cache_. If this cache
-// returns 0 for a particular PageID then that means "no information," not that
-// the sizeclass is 0. The cache may have stale information for pages that do
-// not hold the beginning of any free()'able object. Staleness is eliminated
-// in Populate() for pages with sizeclass > 0 objects, and in do_malloc() and
-// do_memalign() for all other relevant pages.
-//
-// PAGEMAP
-// -------
-// Page map contains a mapping from page id to Span.
-//
-// If Span s occupies pages [p..q],
-// pagemap[p] == s
-// pagemap[q] == s
-// pagemap[p+1..q-1] are undefined
-// pagemap[p-1] and pagemap[q+1] are defined:
-// NULL if the corresponding page is not yet in the address space.
-// Otherwise it points to a Span. This span may be free
-// or allocated. If free, it is in one of pageheap's freelist.
-//
-// TODO: Bias reclamation to larger addresses
-// TODO: implement mallinfo/mallopt
-// TODO: Better testing
-//
-// 9/28/2003 (new page-level allocator replaces ptmalloc2):
-// * malloc/free of small objects goes from ~300 ns to ~50 ns.
-// * allocation of a reasonably complicated struct
-// goes from about 1100 ns to about 300 ns.
-
-#include "config.h"
-#include <gperftools/tcmalloc.h>
-
-#include <errno.h> // for ENOMEM, EINVAL, errno
-#if defined HAVE_STDINT_H
-#include <stdint.h>
-#elif defined HAVE_INTTYPES_H
-#include <inttypes.h>
-#else
-#include <sys/types.h>
-#endif
-#include <stddef.h> // for size_t, NULL
-#include <stdlib.h> // for getenv
-#include <string.h> // for strcmp, memset, strlen, etc
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for getpagesize, write, etc
-#endif
-#include <algorithm> // for max, min
-#include <limits> // for numeric_limits
-#include <new> // for nothrow_t (ptr only), etc
-#include <vector> // for vector
-
-#include <gperftools/malloc_extension.h>
-#include <gperftools/malloc_hook.h> // for MallocHook
-#include "base/basictypes.h" // for int64
-#include "base/commandlineflags.h" // for RegisterFlagValidator, etc
-#include "base/dynamic_annotations.h" // for RunningOnValgrind
-#include "base/spinlock.h" // for SpinLockHolder
-#include "central_freelist.h" // for CentralFreeListPadded
-#include "common.h" // for StackTrace, kPageShift, etc
-#include "internal_logging.h" // for ASSERT, TCMalloc_Printer, etc
-#include "linked_list.h" // for SLL_SetNext
-#include "malloc_hook-inl.h" // for MallocHook::InvokeNewHook, etc
-#include "page_heap.h" // for PageHeap, PageHeap::Stats
-#include "page_heap_allocator.h" // for PageHeapAllocator
-#include "span.h" // for Span, DLL_Prepend, etc
-#include "stack_trace_table.h" // for StackTraceTable
-#include "static_vars.h" // for Static
-#include "system-alloc.h" // for DumpSystemAllocatorStats, etc
-#include "tcmalloc_guard.h" // for TCMallocGuard
-#include "thread_cache.h" // for ThreadCache
-
-#ifdef __clang__
-// clang's apparent focus on code size somehow causes it to ignore
-// normal inline directives even for few functions which inlining is
-// key for performance. In order to get performance of clang's
-// generated code closer to normal, we're forcing inlining via
-// attribute.
-#define ALWAYS_INLINE inline __attribute__((always_inline))
-#else
-#define ALWAYS_INLINE inline
-#endif
-
-#include "maybe_emergency_malloc.h"
-
-#if (defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)) && !defined(WIN32_OVERRIDE_ALLOCATORS)
-# define WIN32_DO_PATCHING 1
-#endif
-
-// Some windows file somewhere (at least on cygwin) #define's small (!)
-#undef small
-
-using STL_NAMESPACE::max;
-using STL_NAMESPACE::numeric_limits;
-using STL_NAMESPACE::vector;
-
-#include "libc_override.h"
-
-using tcmalloc::AlignmentForSize;
-using tcmalloc::kLog;
-using tcmalloc::kCrash;
-using tcmalloc::kCrashWithStats;
-using tcmalloc::Log;
-using tcmalloc::PageHeap;
-using tcmalloc::PageHeapAllocator;
-using tcmalloc::SizeMap;
-using tcmalloc::Span;
-using tcmalloc::StackTrace;
-using tcmalloc::Static;
-using tcmalloc::ThreadCache;
-
-DECLARE_double(tcmalloc_release_rate);
-
-// For windows, the printf we use to report large allocs is
-// potentially dangerous: it could cause a malloc that would cause an
-// infinite loop. So by default we set the threshold to a huge number
-// on windows, so this bad situation will never trigger. You can
-// always set TCMALLOC_LARGE_ALLOC_REPORT_THRESHOLD manually if you
-// want this functionality.
-#ifdef _WIN32
-const int64 kDefaultLargeAllocReportThreshold = static_cast<int64>(1) << 62;
-#else
-const int64 kDefaultLargeAllocReportThreshold = static_cast<int64>(1) << 30;
-#endif
-DEFINE_int64(tcmalloc_large_alloc_report_threshold,
- EnvToInt64("TCMALLOC_LARGE_ALLOC_REPORT_THRESHOLD",
- kDefaultLargeAllocReportThreshold),
- "Allocations larger than this value cause a stack "
- "trace to be dumped to stderr. The threshold for "
- "dumping stack traces is increased by a factor of 1.125 "
- "every time we print a message so that the threshold "
- "automatically goes up by a factor of ~1000 every 60 "
- "messages. This bounds the amount of extra logging "
- "generated by this flag. Default value of this flag "
- "is very large and therefore you should see no extra "
- "logging unless the flag is overridden. Set to 0 to "
- "disable reporting entirely.");
-
-
-// We already declared these functions in tcmalloc.h, but we have to
-// declare them again to give them an ATTRIBUTE_SECTION: we want to
-// put all callers of MallocHook::Invoke* in this module into
-// ATTRIBUTE_SECTION(google_malloc) section, so that
-// MallocHook::GetCallerStackTrace can function accurately.
-#ifndef _WIN32 // windows doesn't have attribute_section, so don't bother
-extern "C" {
- void* tc_malloc(size_t size) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- void tc_free(void* ptr) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- void* tc_realloc(void* ptr, size_t size) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- void tc_cfree(void* ptr) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
-
- void* tc_memalign(size_t __alignment, size_t __size) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- int tc_posix_memalign(void** ptr, size_t align, size_t size) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- void* tc_valloc(size_t __size) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- void* tc_pvalloc(size_t __size) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
-
- void tc_malloc_stats(void) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- int tc_mallopt(int cmd, int value) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
-#ifdef HAVE_STRUCT_MALLINFO
- struct mallinfo tc_mallinfo(void) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
-#endif
-
- void* tc_new(size_t size)
- ATTRIBUTE_SECTION(google_malloc);
- void tc_delete(void* p) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- void* tc_newarray(size_t size)
- ATTRIBUTE_SECTION(google_malloc);
- void tc_deletearray(void* p) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
-
- // And the nothrow variants of these:
- void* tc_new_nothrow(size_t size, const std::nothrow_t&) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- // Surprisingly, standard C++ library implementations use a
- // nothrow-delete internally. See, eg:
- // http://www.dinkumware.com/manuals/?manual=compleat&page=new.html
- void tc_delete_nothrow(void* ptr, const std::nothrow_t&) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
- void tc_deletearray_nothrow(void* ptr, const std::nothrow_t&) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
-
- // Some non-standard extensions that we support.
-
- // This is equivalent to
- // OS X: malloc_size()
- // glibc: malloc_usable_size()
- // Windows: _msize()
- size_t tc_malloc_size(void* p) PERFTOOLS_THROW
- ATTRIBUTE_SECTION(google_malloc);
-} // extern "C"
-#endif // #ifndef _WIN32
-
-// ----------------------- IMPLEMENTATION -------------------------------
-
-static int tc_new_mode = 0; // See tc_set_new_mode().
-
-// Routines such as free() and realloc() catch some erroneous pointers
-// passed to them, and invoke the below when they do. (An erroneous pointer
-// won't be caught if it's within a valid span or a stale span for which
-// the pagemap cache has a non-zero sizeclass.) This is a cheap (source-editing
-// required) kind of exception handling for these routines.
-namespace {
-void InvalidFree(void* ptr) {
- if (tcmalloc::IsEmergencyPtr(ptr)) {
- tcmalloc::EmergencyFree(ptr);
- return;
- }
- Log(kCrash, __FILE__, __LINE__, "Attempt to free invalid pointer", ptr);
-}
-
-size_t InvalidGetSizeForRealloc(const void* old_ptr) {
- Log(kCrash, __FILE__, __LINE__,
- "Attempt to realloc invalid pointer", old_ptr);
- return 0;
-}
-
-size_t InvalidGetAllocatedSize(const void* ptr) {
- Log(kCrash, __FILE__, __LINE__,
- "Attempt to get the size of an invalid pointer", ptr);
- return 0;
-}
-} // unnamed namespace
-
-// Extract interesting stats
-struct TCMallocStats {
- uint64_t thread_bytes; // Bytes in thread caches
- uint64_t central_bytes; // Bytes in central cache
- uint64_t transfer_bytes; // Bytes in central transfer cache
- uint64_t metadata_bytes; // Bytes alloced for metadata
- PageHeap::Stats pageheap; // Stats from page heap
-};
-
-// Get stats into "r". Also, if class_count != NULL, class_count[k]
-// will be set to the total number of objects of size class k in the
-// central cache, transfer cache, and per-thread caches. If small_spans
-// is non-NULL, it is filled. Same for large_spans.
-static void ExtractStats(TCMallocStats* r, uint64_t* class_count,
- PageHeap::SmallSpanStats* small_spans,
- PageHeap::LargeSpanStats* large_spans) {
- r->central_bytes = 0;
- r->transfer_bytes = 0;
- 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) + cache_overhead;
- r->transfer_bytes += (size * tc_length);
- if (class_count) {
- // Sum the lengths of all per-class freelists, except the per-thread
- // freelists, which get counted when we call GetThreadStats(), below.
- class_count[cl] = length + tc_length;
- }
-
- }
-
- // Add stats from per-thread heaps
- r->thread_bytes = 0;
- { // scope
- SpinLockHolder h(Static::pageheap_lock());
- ThreadCache::GetThreadStats(&r->thread_bytes, class_count);
- r->metadata_bytes = tcmalloc::metadata_system_bytes();
- r->pageheap = Static::pageheap()->stats();
- if (small_spans != NULL) {
- Static::pageheap()->GetSmallSpanStats(small_spans);
- }
- if (large_spans != NULL) {
- Static::pageheap()->GetLargeSpanStats(large_spans);
- }
- }
-}
-
-static double PagesToMiB(uint64_t pages) {
- return (pages << kPageShift) / 1048576.0;
-}
-
-// WRITE stats to "out"
-static void DumpStats(TCMalloc_Printer* out, int level) {
- TCMallocStats stats;
- uint64_t class_count[kNumClasses];
- PageHeap::SmallSpanStats small;
- PageHeap::LargeSpanStats large;
- if (level >= 2) {
- ExtractStats(&stats, class_count, &small, &large);
- } else {
- ExtractStats(&stats, NULL, NULL, NULL);
- }
-
- static const double MiB = 1048576.0;
-
- const uint64_t virtual_memory_used = (stats.pageheap.system_bytes
- + stats.metadata_bytes);
- const uint64_t physical_memory_used = (virtual_memory_used
- - stats.pageheap.unmapped_bytes);
- const uint64_t bytes_in_use_by_app = (physical_memory_used
- - stats.metadata_bytes
- - stats.pageheap.free_bytes
- - stats.central_bytes
- - stats.transfer_bytes
- - stats.thread_bytes);
-
-#ifdef TCMALLOC_SMALL_BUT_SLOW
- out->printf(
- "NOTE: SMALL MEMORY MODEL IS IN USE, PERFORMANCE MAY SUFFER.\n");
-#endif
- out->printf(
- "------------------------------------------------\n"
- "MALLOC: %12" PRIu64 " (%7.1f MiB) Bytes in use by application\n"
- "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in page heap freelist\n"
- "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in central cache freelist\n"
- "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in transfer cache freelist\n"
- "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in thread cache freelists\n"
- "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in malloc metadata\n"
- "MALLOC: ------------\n"
- "MALLOC: = %12" PRIu64 " (%7.1f MiB) Actual memory used (physical + swap)\n"
- "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes released to OS (aka unmapped)\n"
- "MALLOC: ------------\n"
- "MALLOC: = %12" PRIu64 " (%7.1f MiB) Virtual address space used\n"
- "MALLOC:\n"
- "MALLOC: %12" PRIu64 " Spans in use\n"
- "MALLOC: %12" PRIu64 " Thread heaps in use\n"
- "MALLOC: %12" PRIu64 " Tcmalloc page size\n"
- "------------------------------------------------\n"
- "Call ReleaseFreeMemory() to release freelist memory to the OS"
- " (via madvise()).\n"
- "Bytes released to the OS take up virtual address space"
- " but no physical memory.\n",
- bytes_in_use_by_app, bytes_in_use_by_app / MiB,
- stats.pageheap.free_bytes, stats.pageheap.free_bytes / MiB,
- stats.central_bytes, stats.central_bytes / MiB,
- stats.transfer_bytes, stats.transfer_bytes / MiB,
- stats.thread_bytes, stats.thread_bytes / MiB,
- stats.metadata_bytes, stats.metadata_bytes / MiB,
- physical_memory_used, physical_memory_used / MiB,
- stats.pageheap.unmapped_bytes, stats.pageheap.unmapped_bytes / MiB,
- virtual_memory_used, virtual_memory_used / MiB,
- uint64_t(Static::span_allocator()->inuse()),
- uint64_t(ThreadCache::HeapsInUse()),
- uint64_t(kPageSize));
-
- if (level >= 2) {
- out->printf("------------------------------------------------\n");
- out->printf("Total size of freelists for per-thread caches,\n");
- out->printf("transfer cache, and central cache, by size class\n");
- out->printf("------------------------------------------------\n");
- uint64_t cumulative = 0;
- for (int cl = 0; cl < kNumClasses; ++cl) {
- if (class_count[cl] > 0) {
- uint64_t class_bytes =
- class_count[cl] * Static::sizemap()->ByteSizeForClass(cl);
- cumulative += class_bytes;
- out->printf("class %3d [ %8" PRIuS " bytes ] : "
- "%8" PRIu64 " objs; %5.1f MiB; %5.1f cum MiB\n",
- cl, Static::sizemap()->ByteSizeForClass(cl),
- class_count[cl],
- class_bytes / MiB,
- cumulative / MiB);
- }
- }
-
- // append page heap info
- int nonempty_sizes = 0;
- for (int s = 0; s < kMaxPages; s++) {
- if (small.normal_length[s] + small.returned_length[s] > 0) {
- nonempty_sizes++;
- }
- }
- out->printf("------------------------------------------------\n");
- out->printf("PageHeap: %d sizes; %6.1f MiB free; %6.1f MiB unmapped\n",
- nonempty_sizes, stats.pageheap.free_bytes / MiB,
- stats.pageheap.unmapped_bytes / MiB);
- out->printf("------------------------------------------------\n");
- uint64_t total_normal = 0;
- uint64_t total_returned = 0;
- for (int s = 0; s < kMaxPages; s++) {
- const int n_length = small.normal_length[s];
- const int r_length = small.returned_length[s];
- if (n_length + r_length > 0) {
- uint64_t n_pages = s * n_length;
- uint64_t r_pages = s * r_length;
- total_normal += n_pages;
- total_returned += r_pages;
- out->printf("%6u pages * %6u spans ~ %6.1f MiB; %6.1f MiB cum"
- "; unmapped: %6.1f MiB; %6.1f MiB cum\n",
- s,
- (n_length + r_length),
- PagesToMiB(n_pages + r_pages),
- PagesToMiB(total_normal + total_returned),
- PagesToMiB(r_pages),
- PagesToMiB(total_returned));
- }
- }
-
- total_normal += large.normal_pages;
- total_returned += large.returned_pages;
- out->printf(">255 large * %6u spans ~ %6.1f MiB; %6.1f MiB cum"
- "; unmapped: %6.1f MiB; %6.1f MiB cum\n",
- static_cast<unsigned int>(large.spans),
- PagesToMiB(large.normal_pages + large.returned_pages),
- PagesToMiB(total_normal + total_returned),
- PagesToMiB(large.returned_pages),
- PagesToMiB(total_returned));
- }
-}
-
-static void PrintStats(int level) {
- const int kBufferSize = 16 << 10;
- char* buffer = new char[kBufferSize];
- TCMalloc_Printer printer(buffer, kBufferSize);
- DumpStats(&printer, level);
- write(STDERR_FILENO, buffer, strlen(buffer));
- delete[] buffer;
-}
-
-static void** DumpHeapGrowthStackTraces() {
- // Count how much space we need
- int needed_slots = 0;
- {
- SpinLockHolder h(Static::pageheap_lock());
- for (StackTrace* t = Static::growth_stacks();
- t != NULL;
- t = reinterpret_cast<StackTrace*>(
- t->stack[tcmalloc::kMaxStackDepth-1])) {
- needed_slots += 3 + t->depth;
- }
- needed_slots += 100; // Slop in case list grows
- needed_slots += needed_slots/8; // An extra 12.5% slop
- }
-
- void** result = new void*[needed_slots];
- if (result == NULL) {
- Log(kLog, __FILE__, __LINE__,
- "tcmalloc: allocation failed for stack trace slots",
- needed_slots * sizeof(*result));
- return NULL;
- }
-
- SpinLockHolder h(Static::pageheap_lock());
- int used_slots = 0;
- for (StackTrace* t = Static::growth_stacks();
- t != NULL;
- t = reinterpret_cast<StackTrace*>(
- t->stack[tcmalloc::kMaxStackDepth-1])) {
- ASSERT(used_slots < needed_slots); // Need to leave room for terminator
- if (used_slots + 3 + t->depth >= needed_slots) {
- // No more room
- break;
- }
-
- result[used_slots+0] = reinterpret_cast<void*>(static_cast<uintptr_t>(1));
- result[used_slots+1] = reinterpret_cast<void*>(t->size);
- result[used_slots+2] = reinterpret_cast<void*>(t->depth);
- for (int d = 0; d < t->depth; d++) {
- result[used_slots+3+d] = t->stack[d];
- }
- used_slots += 3 + t->depth;
- }
- result[used_slots] = reinterpret_cast<void*>(static_cast<uintptr_t>(0));
- return result;
-}
-
-static void IterateOverRanges(void* arg, MallocExtension::RangeFunction func) {
- PageID page = 1; // Some code may assume that page==0 is never used
- bool done = false;
- while (!done) {
- // Accumulate a small number of ranges in a local buffer
- static const int kNumRanges = 16;
- static base::MallocRange ranges[kNumRanges];
- int n = 0;
- {
- SpinLockHolder h(Static::pageheap_lock());
- while (n < kNumRanges) {
- if (!Static::pageheap()->GetNextRange(page, &ranges[n])) {
- done = true;
- break;
- } else {
- uintptr_t limit = ranges[n].address + ranges[n].length;
- page = (limit + kPageSize - 1) >> kPageShift;
- n++;
- }
- }
- }
-
- for (int i = 0; i < n; i++) {
- (*func)(arg, &ranges[i]);
- }
- }
-}
-
-// TCMalloc's support for extra malloc interfaces
-class TCMallocImplementation : public MallocExtension {
- private:
- // ReleaseToSystem() might release more than the requested bytes because
- // the page heap releases at the span granularity, and spans are of wildly
- // different sizes. This member keeps track of the extra bytes bytes
- // released so that the app can periodically call ReleaseToSystem() to
- // release memory at a constant rate.
- // NOTE: Protected by Static::pageheap_lock().
- size_t extra_bytes_released_;
-
- public:
- TCMallocImplementation()
- : extra_bytes_released_(0) {
- }
-
- virtual void GetStats(char* buffer, int buffer_length) {
- ASSERT(buffer_length > 0);
- TCMalloc_Printer printer(buffer, buffer_length);
-
- // Print level one stats unless lots of space is available
- if (buffer_length < 10000) {
- DumpStats(&printer, 1);
- } else {
- DumpStats(&printer, 2);
- }
- }
-
- // We may print an extra, tcmalloc-specific warning message here.
- virtual void GetHeapSample(MallocExtensionWriter* writer) {
- if (FLAGS_tcmalloc_sample_parameter == 0) {
- const char* const kWarningMsg =
- "%warn\n"
- "%warn This heap profile does not have any data in it, because\n"
- "%warn the application was run with heap sampling turned off.\n"
- "%warn To get useful data from GetHeapSample(), you must\n"
- "%warn set the environment variable TCMALLOC_SAMPLE_PARAMETER to\n"
- "%warn a positive sampling period, such as 524288.\n"
- "%warn\n";
- writer->append(kWarningMsg, strlen(kWarningMsg));
- }
- MallocExtension::GetHeapSample(writer);
- }
-
- virtual void** ReadStackTraces(int* sample_period) {
- tcmalloc::StackTraceTable table;
- {
- SpinLockHolder h(Static::pageheap_lock());
- Span* sampled = Static::sampled_objects();
- for (Span* s = sampled->next; s != sampled; s = s->next) {
- table.AddTrace(*reinterpret_cast<StackTrace*>(s->objects));
- }
- }
- *sample_period = ThreadCache::GetCache()->GetSamplePeriod();
- return table.ReadStackTracesAndClear(); // grabs and releases pageheap_lock
- }
-
- virtual void** ReadHeapGrowthStackTraces() {
- return DumpHeapGrowthStackTraces();
- }
-
- virtual size_t GetThreadCacheSize() {
- ThreadCache* tc = ThreadCache::GetCacheIfPresent();
- if (!tc)
- return 0;
- return tc->Size();
- }
-
- virtual void MarkThreadTemporarilyIdle() {
- ThreadCache::BecomeTemporarilyIdle();
- }
-
- virtual void Ranges(void* arg, RangeFunction func) {
- IterateOverRanges(arg, func);
- }
-
- virtual bool GetNumericProperty(const char* name, size_t* value) {
- ASSERT(name != NULL);
-
- if (strcmp(name, "generic.current_allocated_bytes") == 0) {
- TCMallocStats stats;
- ExtractStats(&stats, NULL, NULL, NULL);
- *value = stats.pageheap.system_bytes
- - stats.thread_bytes
- - stats.central_bytes
- - stats.transfer_bytes
- - stats.pageheap.free_bytes
- - stats.pageheap.unmapped_bytes;
- return true;
- }
-
- if (strcmp(name, "generic.heap_size") == 0) {
- TCMallocStats stats;
- ExtractStats(&stats, NULL, NULL, NULL);
- *value = stats.pageheap.system_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.slack_bytes") == 0) {
- // Kept for backwards compatibility. Now defined externally as:
- // pageheap_free_bytes + pageheap_unmapped_bytes.
- SpinLockHolder l(Static::pageheap_lock());
- PageHeap::Stats stats = Static::pageheap()->stats();
- *value = stats.free_bytes + stats.unmapped_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.central_cache_free_bytes") == 0) {
- TCMallocStats stats;
- ExtractStats(&stats, NULL, NULL, NULL);
- *value = stats.central_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.transfer_cache_free_bytes") == 0) {
- TCMallocStats stats;
- ExtractStats(&stats, NULL, NULL, NULL);
- *value = stats.transfer_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.thread_cache_free_bytes") == 0) {
- TCMallocStats stats;
- ExtractStats(&stats, NULL, NULL, NULL);
- *value = stats.thread_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_free_bytes") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().free_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_unmapped_bytes") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().unmapped_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_committed_bytes") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().committed_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_scavenge_count") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().scavenge_count;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_commit_count") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().commit_count;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_total_commit_bytes") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().total_commit_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_decommit_count") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().decommit_count;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_total_decommit_bytes") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().total_decommit_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_reserve_count") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().reserve_count;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.pageheap_total_reserve_bytes") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = Static::pageheap()->stats().total_reserve_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.max_total_thread_cache_bytes") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- *value = ThreadCache::overall_thread_cache_size();
- return true;
- }
-
- if (strcmp(name, "tcmalloc.current_total_thread_cache_bytes") == 0) {
- TCMallocStats stats;
- ExtractStats(&stats, NULL, NULL, NULL);
- *value = stats.thread_bytes;
- return true;
- }
-
- if (strcmp(name, "tcmalloc.aggressive_memory_decommit") == 0) {
- *value = size_t(Static::pageheap()->GetAggressiveDecommit());
- return true;
- }
-
- if (strcmp(name, "tcmalloc.spinlock_total_delay_ns") == 0) {
- *value = SpinLock::GetTotalDelayNanos();
- return true;
- }
-
- return false;
- }
-
- virtual bool SetNumericProperty(const char* name, size_t value) {
- ASSERT(name != NULL);
-
- if (strcmp(name, "tcmalloc.max_total_thread_cache_bytes") == 0) {
- SpinLockHolder l(Static::pageheap_lock());
- ThreadCache::set_overall_thread_cache_size(value);
- return true;
- }
-
- if (strcmp(name, "tcmalloc.aggressive_memory_decommit") == 0) {
- Static::pageheap()->SetAggressiveDecommit(value != 0);
- return true;
- }
-
- return false;
- }
-
- virtual void MarkThreadIdle() {
- ThreadCache::BecomeIdle();
- }
-
- virtual void MarkThreadBusy(); // Implemented below
-
- virtual SysAllocator* GetSystemAllocator() {
- SpinLockHolder h(Static::pageheap_lock());
- return sys_alloc;
- }
-
- virtual void SetSystemAllocator(SysAllocator* alloc) {
- SpinLockHolder h(Static::pageheap_lock());
- sys_alloc = alloc;
- }
-
- virtual void ReleaseToSystem(size_t num_bytes) {
- SpinLockHolder h(Static::pageheap_lock());
- if (num_bytes <= extra_bytes_released_) {
- // We released too much on a prior call, so don't release any
- // more this time.
- extra_bytes_released_ = extra_bytes_released_ - num_bytes;
- return;
- }
- num_bytes = num_bytes - extra_bytes_released_;
- // num_bytes might be less than one page. If we pass zero to
- // ReleaseAtLeastNPages, it won't do anything, so we release a whole
- // page now and let extra_bytes_released_ smooth it out over time.
- Length num_pages = max<Length>(num_bytes >> kPageShift, 1);
- size_t bytes_released = Static::pageheap()->ReleaseAtLeastNPages(
- num_pages) << kPageShift;
- if (bytes_released > num_bytes) {
- extra_bytes_released_ = bytes_released - num_bytes;
- } else {
- // The PageHeap wasn't able to release num_bytes. Don't try to
- // compensate with a big release next time. Specifically,
- // ReleaseFreeMemory() calls ReleaseToSystem(LONG_MAX).
- extra_bytes_released_ = 0;
- }
- }
-
- virtual void SetMemoryReleaseRate(double rate) {
- FLAGS_tcmalloc_release_rate = rate;
- }
-
- virtual double GetMemoryReleaseRate() {
- return FLAGS_tcmalloc_release_rate;
- }
- virtual size_t GetEstimatedAllocatedSize(size_t size) {
- if (size <= kMaxSize) {
- const size_t cl = Static::sizemap()->SizeClass(size);
- const size_t alloc_size = Static::sizemap()->ByteSizeForClass(cl);
- return alloc_size;
- } else {
- return tcmalloc::pages(size) << kPageShift;
- }
- }
-
- // This just calls GetSizeWithCallback, but because that's in an
- // unnamed namespace, we need to move the definition below it in the
- // file.
- virtual size_t GetAllocatedSize(const 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";
- static const char* kThreadCacheType = "tcmalloc.thread";
- static const char* kPageHeapType = "tcmalloc.page";
- static const char* kPageHeapUnmappedType = "tcmalloc.page_unmapped";
- static const char* kLargeSpanType = "tcmalloc.large";
- static const char* kLargeUnmappedSpanType = "tcmalloc.large_unmapped";
-
- v->clear();
-
- // central class information
- int64 prev_class_size = 0;
- for (int cl = 1; cl < kNumClasses; ++cl) {
- size_t class_size = Static::sizemap()->ByteSizeForClass(cl);
- MallocExtension::FreeListInfo i;
- i.min_object_size = prev_class_size + 1;
- i.max_object_size = class_size;
- i.total_bytes_free =
- Static::central_cache()[cl].length() * class_size;
- i.type = kCentralCacheType;
- v->push_back(i);
-
- // transfer cache
- i.total_bytes_free =
- Static::central_cache()[cl].tc_length() * class_size;
- i.type = kTransferCacheType;
- v->push_back(i);
-
- prev_class_size = Static::sizemap()->ByteSizeForClass(cl);
- }
-
- // Add stats from per-thread heaps
- uint64_t class_count[kNumClasses];
- memset(class_count, 0, sizeof(class_count));
- {
- SpinLockHolder h(Static::pageheap_lock());
- uint64_t thread_bytes = 0;
- ThreadCache::GetThreadStats(&thread_bytes, class_count);
- }
-
- prev_class_size = 0;
- for (int cl = 1; cl < kNumClasses; ++cl) {
- MallocExtension::FreeListInfo i;
- i.min_object_size = prev_class_size + 1;
- i.max_object_size = Static::sizemap()->ByteSizeForClass(cl);
- i.total_bytes_free =
- class_count[cl] * Static::sizemap()->ByteSizeForClass(cl);
- i.type = kThreadCacheType;
- v->push_back(i);
- }
-
- // append page heap info
- PageHeap::SmallSpanStats small;
- PageHeap::LargeSpanStats large;
- {
- SpinLockHolder h(Static::pageheap_lock());
- Static::pageheap()->GetSmallSpanStats(&small);
- Static::pageheap()->GetLargeSpanStats(&large);
- }
-
- // large spans: mapped
- MallocExtension::FreeListInfo span_info;
- span_info.type = kLargeSpanType;
- span_info.max_object_size = (numeric_limits<size_t>::max)();
- span_info.min_object_size = kMaxPages << kPageShift;
- span_info.total_bytes_free = large.normal_pages << kPageShift;
- v->push_back(span_info);
-
- // large spans: unmapped
- span_info.type = kLargeUnmappedSpanType;
- span_info.total_bytes_free = large.returned_pages << kPageShift;
- v->push_back(span_info);
-
- // small spans
- for (int s = 1; s < kMaxPages; s++) {
- MallocExtension::FreeListInfo i;
- i.max_object_size = (s << kPageShift);
- i.min_object_size = ((s - 1) << kPageShift);
-
- i.type = kPageHeapType;
- i.total_bytes_free = (s << kPageShift) * small.normal_length[s];
- v->push_back(i);
-
- i.type = kPageHeapUnmappedType;
- i.total_bytes_free = (s << kPageShift) * small.returned_length[s];
- v->push_back(i);
- }
- }
-
- virtual void SizeClasses(void* arg, SizeClassFunction func) {
- TCMallocStats global_stats;
- base::MallocSizeClass stats;
- uint64_t class_count[kNumClasses];
- ExtractStats(&global_stats, class_count, NULL, NULL);
-
- for (int cl = 0; cl < kNumClasses; cl++) {
- uint64_t central_objs = Static::central_cache()[cl].length();
- uint64_t transfer_objs = Static::central_cache()[cl].tc_length();
- uint64_t num_spans = Static::central_cache()[cl].spans();
- uint64_t pages_per_span = Static::sizemap()->class_to_pages(cl);
-
- stats.bytes_per_obj = Static::sizemap()->ByteSizeForClass(cl);
- stats.pages_per_span = pages_per_span;
- stats.num_spans = num_spans;
- stats.num_central_objs = central_objs;
- stats.num_transfer_objs = transfer_objs;
- stats.num_thread_objs = class_count[cl] - central_objs - transfer_objs;
- stats.free_bytes = class_count[cl] * Static::sizemap()->ByteSizeForClass(cl);
- stats.alloc_bytes = (num_spans * pages_per_span) << kPageShift;
-
- func(arg, &stats);
- }
- }
-};
-
-// The constructor allocates an object to ensure that initialization
-// runs before main(), and therefore we do not have a chance to become
-// multi-threaded before initialization. We also create the TSD key
-// here. Presumably by the time this constructor runs, glibc is in
-// good enough shape to handle pthread_key_create().
-//
-// The constructor also takes the opportunity to tell STL to use
-// tcmalloc. We want to do this early, before construct time, so
-// all user STL allocations go through tcmalloc (which works really
-// well for STL).
-//
-// The destructor prints stats when the program exits.
-static int tcmallocguard_refcount = 0; // no lock needed: runs before main()
-TCMallocGuard::TCMallocGuard() {
- if (tcmallocguard_refcount++ == 0) {
- ReplaceSystemAlloc(); // defined in libc_override_*.h
- tc_free(tc_malloc(1));
- ThreadCache::InitTSD();
- tc_free(tc_malloc(1));
- // Either we, or debugallocation.cc, or valgrind will control memory
- // management. We register our extension if we're the winner.
-#ifdef TCMALLOC_USING_DEBUGALLOCATION
- // Let debugallocation register its extension.
-#else
- if (RunningOnValgrind()) {
- // Let Valgrind uses its own malloc (so don't register our extension).
- } else {
- MallocExtension::Register(new TCMallocImplementation);
- }
-#endif
- }
-}
-
-TCMallocGuard::~TCMallocGuard() {
- if (--tcmallocguard_refcount == 0) {
- const char* env = NULL;
- if (!RunningOnValgrind()) {
- // Valgrind uses it's own malloc so we cannot do MALLOCSTATS
- env = getenv("MALLOCSTATS");
- }
- if (env != NULL) {
- int level = atoi(env);
- if (level < 1) level = 1;
- PrintStats(level);
- }
- }
-}
-#ifndef WIN32_OVERRIDE_ALLOCATORS
-static TCMallocGuard module_enter_exit_hook;
-#endif
-
-//-------------------------------------------------------------------
-// Helpers for the exported routines below
-//-------------------------------------------------------------------
-
-static inline bool CheckCachedSizeClass(void *ptr) {
- PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
- size_t cached_value = Static::pageheap()->GetSizeClassIfCached(p);
- return cached_value == 0 ||
- cached_value == Static::pageheap()->GetDescriptor(p)->sizeclass;
-}
-
-static inline void* CheckedMallocResult(void *result) {
- ASSERT(result == NULL || CheckCachedSizeClass(result));
- return result;
-}
-
-static inline void* SpanToMallocResult(Span *span) {
- Static::pageheap()->CacheSizeClass(span->start, 0);
- return
- CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift));
-}
-
-static void* DoSampledAllocation(size_t size) {
-#ifndef NO_TCMALLOC_SAMPLES
- // Grab the stack trace outside the heap lock
- StackTrace tmp;
- tmp.depth = GetStackTrace(tmp.stack, tcmalloc::kMaxStackDepth, 1);
- tmp.size = size;
-
- SpinLockHolder h(Static::pageheap_lock());
- // Allocate span
- Span *span = Static::pageheap()->New(tcmalloc::pages(size == 0 ? 1 : size));
- if (UNLIKELY(span == NULL)) {
- return NULL;
- }
-
- // Allocate stack trace
- StackTrace *stack = Static::stacktrace_allocator()->New();
- if (UNLIKELY(stack == NULL)) {
- // Sampling failed because of lack of memory
- return span;
- }
- *stack = tmp;
- span->sample = 1;
- span->objects = stack;
- tcmalloc::DLL_Prepend(Static::sampled_objects(), span);
-
- return SpanToMallocResult(span);
-#else
- abort();
-#endif
-}
-
-namespace {
-
-typedef void* (*malloc_fn)(void *arg);
-
-SpinLock set_new_handler_lock(SpinLock::LINKER_INITIALIZED);
-
-void* handle_oom(malloc_fn retry_fn,
- void* retry_arg,
- bool from_operator,
- bool nothrow) {
- if (!from_operator && !tc_new_mode) {
- // we're out of memory in C library function (malloc etc) and no
- // "new mode" forced on us. Just return NULL
- return NULL;
- }
- // we're OOM in operator new or "new mode" is set. We might have to
- // call new_handle and maybe retry allocation.
-
- for (;;) {
- // Get the current new handler. NB: this function is not
- // thread-safe. We make a feeble stab at making it so here, but
- // this lock only protects against tcmalloc interfering with
- // itself, not with other libraries calling set_new_handler.
- std::new_handler nh;
- {
- SpinLockHolder h(&set_new_handler_lock);
- nh = std::set_new_handler(0);
- (void) std::set_new_handler(nh);
- }
-#if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
- if (!nh) {
- return NULL;
- }
- // Since exceptions are disabled, we don't really know if new_handler
- // failed. Assume it will abort if it fails.
- (*nh)();
-#else
- // If no new_handler is established, the allocation failed.
- if (!nh) {
- if (nothrow) {
- return NULL;
- }
- throw std::bad_alloc();
- }
- // Otherwise, try the new_handler. If it returns, retry the
- // allocation. If it throws std::bad_alloc, fail the allocation.
- // if it throws something else, don't interfere.
- try {
- (*nh)();
- } catch (const std::bad_alloc&) {
- if (!nothrow) throw;
- return NULL;
- }
-#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
-
- // we get here if new_handler returns successfully. So we retry
- // allocation.
- void* rv = retry_fn(retry_arg);
- if (rv != NULL) {
- return rv;
- }
-
- // if allocation failed again we go to next loop iteration
- }
-}
-
-// Copy of FLAGS_tcmalloc_large_alloc_report_threshold with
-// automatic increases factored in.
-static int64_t large_alloc_threshold =
- (kPageSize > FLAGS_tcmalloc_large_alloc_report_threshold
- ? kPageSize : FLAGS_tcmalloc_large_alloc_report_threshold);
-
-static void ReportLargeAlloc(Length num_pages, void* result) {
- StackTrace stack;
- stack.depth = GetStackTrace(stack.stack, tcmalloc::kMaxStackDepth, 1);
-
- static const int N = 1000;
- char buffer[N];
- TCMalloc_Printer printer(buffer, N);
- 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]);
- }
- printer.printf("\n");
- write(STDERR_FILENO, buffer, strlen(buffer));
-}
-
-void* do_memalign(size_t align, size_t size);
-
-struct retry_memaligh_data {
- size_t align;
- size_t size;
-};
-
-static void *retry_do_memalign(void *arg) {
- retry_memaligh_data *data = static_cast<retry_memaligh_data *>(arg);
- return do_memalign(data->align, data->size);
-}
-
-static void *maybe_do_cpp_memalign_slow(size_t align, size_t size) {
- retry_memaligh_data data;
- data.align = align;
- data.size = size;
- return handle_oom(retry_do_memalign, &data,
- false, true);
-}
-
-inline void* do_memalign_or_cpp_memalign(size_t align, size_t size) {
- void *rv = do_memalign(align, size);
- if (LIKELY(rv != NULL)) {
- return rv;
- }
- return maybe_do_cpp_memalign_slow(align, size);
-}
-
-// Must be called with the page lock held.
-inline bool should_report_large(Length num_pages) {
- const int64 threshold = large_alloc_threshold;
- if (threshold > 0 && num_pages >= (threshold >> kPageShift)) {
- // Increase the threshold by 1/8 every time we generate a report.
- // We cap the threshold at 8GiB to avoid overflow problems.
- large_alloc_threshold = (threshold + threshold/8 < 8ll<<30
- ? threshold + threshold/8 : 8ll<<30);
- return true;
- }
- return false;
-}
-
-// Helper for do_malloc().
-inline void* do_malloc_pages(ThreadCache* heap, size_t size) {
- void* result;
- bool report_large;
-
- Length num_pages = tcmalloc::pages(size);
-
- // NOTE: we're passing original size here as opposed to rounded-up
- // size as we do in do_malloc_small. The difference is small here
- // (at most 4k out of at least 256k). And not rounding up saves us
- // from possibility of overflow, which rounding up could produce.
- //
- // See https://github.com/gperftools/gperftools/issues/723
- if (heap->SampleAllocation(size)) {
- result = DoSampledAllocation(size);
-
- SpinLockHolder h(Static::pageheap_lock());
- report_large = should_report_large(num_pages);
- } else {
- SpinLockHolder h(Static::pageheap_lock());
- Span* span = Static::pageheap()->New(num_pages);
- result = (UNLIKELY(span == NULL) ? NULL : SpanToMallocResult(span));
- report_large = should_report_large(num_pages);
- }
-
- if (report_large) {
- ReportLargeAlloc(num_pages, result);
- }
- return result;
-}
-
-ALWAYS_INLINE void* do_malloc_small(ThreadCache* heap, size_t size) {
- ASSERT(Static::IsInited());
- ASSERT(heap != NULL);
- size_t cl = Static::sizemap()->SizeClass(size);
- size = Static::sizemap()->class_to_size(cl);
-
- if (UNLIKELY(heap->SampleAllocation(size))) {
- return DoSampledAllocation(size);
- } else {
- // The common case, and also the simplest. This just pops the
- // size-appropriate freelist, after replenishing it if it's empty.
- return CheckedMallocResult(heap->Allocate(size, cl));
- }
-}
-
-ALWAYS_INLINE void* do_malloc(size_t size) {
- if (ThreadCache::have_tls) {
- if (LIKELY(size < ThreadCache::MinSizeForSlowPath())) {
- return do_malloc_small(ThreadCache::GetCacheWhichMustBePresent(), size);
- }
- if (UNLIKELY(ThreadCache::IsUseEmergencyMalloc())) {
- return tcmalloc::EmergencyMalloc(size);
- }
- }
-
- if (size <= kMaxSize) {
- return do_malloc_small(ThreadCache::GetCache(), size);
- } else {
- return do_malloc_pages(ThreadCache::GetCache(), size);
- }
-}
-
-static void *retry_malloc(void* size) {
- return do_malloc(reinterpret_cast<size_t>(size));
-}
-
-ALWAYS_INLINE void* do_malloc_or_cpp_alloc(size_t size) {
- void *rv = do_malloc(size);
- if (LIKELY(rv != NULL)) {
- return rv;
- }
- return handle_oom(retry_malloc, reinterpret_cast<void *>(size),
- false, true);
-}
-
-ALWAYS_INLINE void* do_calloc(size_t n, size_t elem_size) {
- // Overflow check
- const size_t size = n * elem_size;
- if (elem_size != 0 && size / elem_size != n) return NULL;
-
- void* result = do_malloc_or_cpp_alloc(size);
- if (result != NULL) {
- memset(result, 0, size);
- }
- return result;
-}
-
-// If ptr is NULL, do nothing. Otherwise invoke the given function.
-inline void free_null_or_invalid(void* ptr, void (*invalid_free_fn)(void*)) {
- if (ptr != NULL) {
- (*invalid_free_fn)(ptr);
- }
-}
-
-// Helper for do_free_with_callback(), below. Inputs:
-// ptr is object to be freed
-// invalid_free_fn is a function that gets invoked on certain "bad frees"
-// heap is the ThreadCache for this thread, or NULL if it isn't known
-// heap_must_be_valid is whether heap is known to be non-NULL
-//
-// This function may only be used after Static::IsInited() is true.
-//
-// We can usually detect the case where ptr is not pointing to a page that
-// tcmalloc is using, and in those cases we invoke invalid_free_fn.
-//
-// To maximize speed in the common case, we usually get here with
-// heap_must_be_valid being a manifest constant equal to true.
-ALWAYS_INLINE void do_free_helper(void* ptr,
- void (*invalid_free_fn)(void*),
- ThreadCache* heap,
- bool heap_must_be_valid,
- bool use_hint,
- size_t size_hint) {
- ASSERT((Static::IsInited() && heap != NULL) || !heap_must_be_valid);
- if (!heap_must_be_valid && !Static::IsInited()) {
- // We called free() before malloc(). This can occur if the
- // (system) malloc() is called before tcmalloc is loaded, and then
- // free() is called after tcmalloc is loaded (and tc_free has
- // replaced free), but before the global constructor has run that
- // sets up the tcmalloc data structures.
- free_null_or_invalid(ptr, invalid_free_fn);
- return;
- }
- Span* span = NULL;
- const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
- size_t cl;
- if (use_hint && Static::sizemap()->MaybeSizeClass(size_hint, &cl)) {
- goto non_zero;
- }
-
- cl = Static::pageheap()->GetSizeClassIfCached(p);
- if (UNLIKELY(cl == 0)) {
- span = Static::pageheap()->GetDescriptor(p);
- if (UNLIKELY(!span)) {
- // span can be NULL because the pointer passed in is NULL or invalid
- // (not something returned by malloc or friends), or because the
- // pointer was allocated with some other allocator besides
- // tcmalloc. The latter can happen if tcmalloc is linked in via
- // a dynamic library, but is not listed last on the link line.
- // In that case, libraries after it on the link line will
- // allocate with libc malloc, but free with tcmalloc's free.
- free_null_or_invalid(ptr, invalid_free_fn);
- return;
- }
- cl = span->sizeclass;
- Static::pageheap()->CacheSizeClass(p, cl);
- }
-
- ASSERT(ptr != NULL);
- if (LIKELY(cl != 0)) {
- non_zero:
- ASSERT(!Static::pageheap()->GetDescriptor(p)->sample);
- if (heap_must_be_valid || heap != NULL) {
- heap->Deallocate(ptr, cl);
- } else {
- // Delete directly into central cache
- tcmalloc::SLL_SetNext(ptr, NULL);
- Static::central_cache()[cl].InsertRange(ptr, ptr, 1);
- }
- } else {
- SpinLockHolder h(Static::pageheap_lock());
- ASSERT(reinterpret_cast<uintptr_t>(ptr) % kPageSize == 0);
- ASSERT(span != NULL && span->start == p);
- if (span->sample) {
- StackTrace* st = reinterpret_cast<StackTrace*>(span->objects);
- tcmalloc::DLL_Remove(span);
- Static::stacktrace_allocator()->Delete(st);
- span->objects = NULL;
- }
- Static::pageheap()->Delete(span);
- }
-}
-
-// Helper for the object deletion (free, delete, etc.). Inputs:
-// ptr is object to be freed
-// invalid_free_fn is a function that gets invoked on certain "bad frees"
-//
-// We can usually detect the case where ptr is not pointing to a page that
-// tcmalloc is using, and in those cases we invoke invalid_free_fn.
-ALWAYS_INLINE void do_free_with_callback(void* ptr,
- void (*invalid_free_fn)(void*),
- bool use_hint, size_t size_hint) {
- ThreadCache* heap = NULL;
- heap = ThreadCache::GetCacheIfPresent();
- if (LIKELY(heap)) {
- do_free_helper(ptr, invalid_free_fn, heap, true, use_hint, size_hint);
- } else {
- do_free_helper(ptr, invalid_free_fn, heap, false, use_hint, size_hint);
- }
-}
-
-// The default "do_free" that uses the default callback.
-ALWAYS_INLINE void do_free(void* ptr) {
- return do_free_with_callback(ptr, &InvalidFree, false, 0);
-}
-
-// 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(const void* ptr,
- size_t (*invalid_getsize_fn)(const void*)) {
- if (ptr == NULL)
- return 0;
- const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
- size_t cl = Static::pageheap()->GetSizeClassIfCached(p);
- if (cl != 0) {
- return Static::sizemap()->ByteSizeForClass(cl);
- } else {
- const Span *span = Static::pageheap()->GetDescriptor(p);
- if (UNLIKELY(span == NULL)) { // means we do not own this memory
- return (*invalid_getsize_fn)(ptr);
- } else if (span->sizeclass != 0) {
- Static::pageheap()->CacheSizeClass(p, span->sizeclass);
- return Static::sizemap()->ByteSizeForClass(span->sizeclass);
- } else {
- return span->length << kPageShift;
- }
- }
-}
-
-// This lets you call back to a given function pointer if ptr is invalid.
-// It is used primarily by windows code which wants a specialized callback.
-ALWAYS_INLINE void* do_realloc_with_callback(
- void* old_ptr, size_t new_size,
- void (*invalid_free_fn)(void*),
- size_t (*invalid_get_size_fn)(const void*)) {
- // Get the size of the old entry
- const size_t old_size = GetSizeWithCallback(old_ptr, invalid_get_size_fn);
-
- // Reallocate if the new size is larger than the old size,
- // or if the new size is significantly smaller than the old size.
- // We do hysteresis to avoid resizing ping-pongs:
- // . If we need to grow, grow to max(new_size, old_size * 1.X)
- // . Don't shrink unless new_size < old_size * 0.Y
- // X and Y trade-off time for wasted space. For now we do 1.25 and 0.5.
- const size_t lower_bound_to_grow = old_size + old_size / 4ul;
- const size_t upper_bound_to_shrink = old_size / 2ul;
- if ((new_size > old_size) || (new_size < upper_bound_to_shrink)) {
- // Need to reallocate.
- void* new_ptr = NULL;
-
- if (new_size > old_size && new_size < lower_bound_to_grow) {
- new_ptr = do_malloc_or_cpp_alloc(lower_bound_to_grow);
- }
- if (new_ptr == NULL) {
- // Either new_size is not a tiny increment, or last do_malloc failed.
- new_ptr = do_malloc_or_cpp_alloc(new_size);
- }
- if (UNLIKELY(new_ptr == NULL)) {
- return NULL;
- }
- MallocHook::InvokeNewHook(new_ptr, new_size);
- memcpy(new_ptr, old_ptr, ((old_size < new_size) ? old_size : new_size));
- MallocHook::InvokeDeleteHook(old_ptr);
- // We could use a variant of do_free() that leverages the fact
- // that we already know the sizeclass of old_ptr. The benefit
- // would be small, so don't bother.
- do_free_with_callback(old_ptr, invalid_free_fn, false, 0);
- return new_ptr;
- } else {
- // We still need to call hooks to report the updated size:
- MallocHook::InvokeDeleteHook(old_ptr);
- MallocHook::InvokeNewHook(old_ptr, new_size);
- return old_ptr;
- }
-}
-
-ALWAYS_INLINE void* do_realloc(void* old_ptr, size_t new_size) {
- return do_realloc_with_callback(old_ptr, new_size,
- &InvalidFree, &InvalidGetSizeForRealloc);
-}
-
-// For use by exported routines below that want specific alignments
-//
-// Note: this code can be slow for alignments > 16, and can
-// significantly fragment memory. The expectation is that
-// memalign/posix_memalign/valloc/pvalloc will not be invoked very
-// often. This requirement simplifies our implementation and allows
-// us to tune for expected allocation patterns.
-void* do_memalign(size_t align, size_t size) {
- ASSERT((align & (align - 1)) == 0);
- ASSERT(align > 0);
- if (size + align < size) return NULL; // Overflow
-
- // Fall back to malloc if we would already align this memory access properly.
- if (align <= AlignmentForSize(size)) {
- void* p = do_malloc(size);
- ASSERT((reinterpret_cast<uintptr_t>(p) % align) == 0);
- return p;
- }
-
- if (UNLIKELY(Static::pageheap() == NULL)) ThreadCache::InitModule();
-
- // Allocate at least one byte to avoid boundary conditions below
- if (size == 0) size = 1;
-
- if (size <= kMaxSize && align < kPageSize) {
- // Search through acceptable size classes looking for one with
- // enough alignment. This depends on the fact that
- // InitSizeClasses() currently produces several size classes that
- // are aligned at powers of two. We will waste time and space if
- // we miss in the size class array, but that is deemed acceptable
- // since memalign() should be used rarely.
- int cl = Static::sizemap()->SizeClass(size);
- while (cl < kNumClasses &&
- ((Static::sizemap()->class_to_size(cl) & (align - 1)) != 0)) {
- cl++;
- }
- if (cl < kNumClasses) {
- ThreadCache* heap = ThreadCache::GetCache();
- size = Static::sizemap()->class_to_size(cl);
- return CheckedMallocResult(heap->Allocate(size, cl));
- }
- }
-
- // We will allocate directly from the page heap
- SpinLockHolder h(Static::pageheap_lock());
-
- if (align <= kPageSize) {
- // Any page-level allocation will be fine
- // TODO: We could put the rest of this page in the appropriate
- // TODO: cache but it does not seem worth it.
- Span* span = Static::pageheap()->New(tcmalloc::pages(size));
- return UNLIKELY(span == NULL) ? NULL : SpanToMallocResult(span);
- }
-
- // Allocate extra pages and carve off an aligned portion
- const Length alloc = tcmalloc::pages(size + align);
- Span* span = Static::pageheap()->New(alloc);
- if (UNLIKELY(span == NULL)) return NULL;
-
- // Skip starting portion so that we end up aligned
- Length skip = 0;
- while ((((span->start+skip) << kPageShift) & (align - 1)) != 0) {
- skip++;
- }
- ASSERT(skip < alloc);
- if (skip > 0) {
- Span* rest = Static::pageheap()->Split(span, skip);
- Static::pageheap()->Delete(span);
- span = rest;
- }
-
- // Skip trailing portion that we do not need to return
- const Length needed = tcmalloc::pages(size);
- ASSERT(span->length >= needed);
- if (span->length > needed) {
- Span* trailer = Static::pageheap()->Split(span, needed);
- Static::pageheap()->Delete(trailer);
- }
- return SpanToMallocResult(span);
-}
-
-// Helpers for use by exported routines below:
-
-inline void do_malloc_stats() {
- PrintStats(1);
-}
-
-inline int do_mallopt(int cmd, int value) {
- return 1; // Indicates error
-}
-
-#ifdef HAVE_STRUCT_MALLINFO
-inline struct mallinfo do_mallinfo() {
- TCMallocStats stats;
- ExtractStats(&stats, NULL, NULL, NULL);
-
- // Just some of the fields are filled in.
- struct mallinfo info;
- memset(&info, 0, sizeof(info));
-
- // Unfortunately, the struct contains "int" field, so some of the
- // size values will be truncated.
- info.arena = static_cast<int>(stats.pageheap.system_bytes);
- info.fsmblks = static_cast<int>(stats.thread_bytes
- + stats.central_bytes
- + stats.transfer_bytes);
- info.fordblks = static_cast<int>(stats.pageheap.free_bytes +
- stats.pageheap.unmapped_bytes);
- info.uordblks = static_cast<int>(stats.pageheap.system_bytes
- - stats.thread_bytes
- - stats.central_bytes
- - stats.transfer_bytes
- - stats.pageheap.free_bytes
- - stats.pageheap.unmapped_bytes);
-
- return info;
-}
-#endif // HAVE_STRUCT_MALLINFO
-
-inline void* cpp_alloc(size_t size, bool nothrow) {
- void* p = do_malloc(size);
- if (LIKELY(p)) {
- return p;
- }
- return handle_oom(retry_malloc, reinterpret_cast<void *>(size),
- true, nothrow);
-}
-
-} // end unnamed namespace
-
-// As promised, the definition of this function, declared above.
-size_t TCMallocImplementation::GetAllocatedSize(const void* ptr) {
- if (ptr == NULL)
- return 0;
- ASSERT(TCMallocImplementation::GetOwnership(ptr)
- != TCMallocImplementation::kNotOwned);
- return GetSizeWithCallback(ptr, &InvalidGetAllocatedSize);
-}
-
-void TCMallocImplementation::MarkThreadBusy() {
- // Allocate to force the creation of a thread cache, but avoid
- // invoking any hooks.
- do_free(do_malloc(0));
-}
-
-//-------------------------------------------------------------------
-// Exported routines
-//-------------------------------------------------------------------
-
-extern "C" PERFTOOLS_DLL_DECL const char* tc_version(
- int* major, int* minor, const char** patch) PERFTOOLS_THROW {
- if (major) *major = TC_VERSION_MAJOR;
- if (minor) *minor = TC_VERSION_MINOR;
- if (patch) *patch = TC_VERSION_PATCH;
- return TC_VERSION_STRING;
-}
-
-// This function behaves similarly to MSVC's _set_new_mode.
-// If flag is 0 (default), calls to malloc will behave normally.
-// If flag is 1, calls to malloc will behave like calls to new,
-// and the std_new_handler will be invoked on failure.
-// Returns the previous mode.
-extern "C" PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_THROW {
- int old_mode = tc_new_mode;
- tc_new_mode = flag;
- return old_mode;
-}
-
-#ifndef TCMALLOC_USING_DEBUGALLOCATION // debugallocation.cc defines its own
-
-#if defined(__GNUC__) && defined(__ELF__) && !defined(TCMALLOC_NO_ALIASES)
-#define TC_ALIAS(name) __attribute__((alias(#name)))
-#endif
-
-// CAVEAT: The code structure below ensures that MallocHook methods are always
-// called from the stack frame of the invoked allocation function.
-// heap-checker.cc depends on this to start a stack trace from
-// the call to the (de)allocation function.
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_THROW {
- void* result = do_malloc_or_cpp_alloc(size);
- MallocHook::InvokeNewHook(result, size);
- return result;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_THROW {
- MallocHook::InvokeDeleteHook(ptr);
- do_free(ptr);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_THROW {
- if ((reinterpret_cast<uintptr_t>(ptr) & (kPageSize-1)) == 0) {
- tc_free(ptr);
- return;
- }
- MallocHook::InvokeDeleteHook(ptr);
- do_free_with_callback(ptr, &InvalidFree, true, size);
-}
-
-#ifdef TC_ALIAS
-
-extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized(void *p, size_t size) throw()
- TC_ALIAS(tc_free_sized);
-extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized(void *p, size_t size) throw()
- TC_ALIAS(tc_free_sized);
-
-#else
-
-extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized(void *p, size_t size) throw() {
- tc_free_sized(p, size);
-}
-extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized(void *p, size_t size) throw() {
- tc_free_sized(p, size);
-}
-
-#endif
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t n,
- size_t elem_size) PERFTOOLS_THROW {
- if (ThreadCache::IsUseEmergencyMalloc()) {
- return tcmalloc::EmergencyCalloc(n, elem_size);
- }
- void* result = do_calloc(n, elem_size);
- MallocHook::InvokeNewHook(result, n * elem_size);
- return result;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_THROW
-#ifdef TC_ALIAS
-TC_ALIAS(tc_free);
-#else
-{
- MallocHook::InvokeDeleteHook(ptr);
- do_free(ptr);
-}
-#endif
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* old_ptr,
- size_t new_size) PERFTOOLS_THROW {
- if (old_ptr == NULL) {
- void* result = do_malloc_or_cpp_alloc(new_size);
- MallocHook::InvokeNewHook(result, new_size);
- return result;
- }
- if (new_size == 0) {
- MallocHook::InvokeDeleteHook(old_ptr);
- do_free(old_ptr);
- return NULL;
- }
- if (UNLIKELY(tcmalloc::IsEmergencyPtr(old_ptr))) {
- return tcmalloc::EmergencyRealloc(old_ptr, new_size);
- }
- return do_realloc(old_ptr, new_size);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_new(size_t size) {
- void* p = cpp_alloc(size, false);
- // We keep this next instruction out of cpp_alloc for a reason: when
- // it's in, and new just calls cpp_alloc, the optimizer may fold the
- // new call into cpp_alloc, which messes up our whole section-based
- // stacktracing (see ATTRIBUTE_SECTION, above). This ensures cpp_alloc
- // isn't the last thing this fn calls, and prevents the folding.
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) PERFTOOLS_THROW {
- void* p = cpp_alloc(size, true);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_THROW
-#ifdef TC_ALIAS
-TC_ALIAS(tc_free);
-#else
-{
- MallocHook::InvokeDeleteHook(p);
- do_free(p);
-}
-#endif
-
-// Standard C++ library implementations define and use this
-// (via ::operator delete(ptr, nothrow)).
-// But it's really the same as normal delete, so we just do the same thing.
-extern "C" PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, const std::nothrow_t&) PERFTOOLS_THROW
-#ifdef TC_ALIAS
-TC_ALIAS(tc_free);
-#else
-{
- MallocHook::InvokeDeleteHook(p);
- do_free(p);
-}
-#endif
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size)
-#ifdef TC_ALIAS
-TC_ALIAS(tc_new);
-#else
-{
- void* p = cpp_alloc(size, false);
- // We keep this next instruction out of cpp_alloc for a reason: when
- // it's in, and new just calls cpp_alloc, the optimizer may fold the
- // new call into cpp_alloc, which messes up our whole section-based
- // stacktracing (see ATTRIBUTE_SECTION, above). This ensures cpp_alloc
- // isn't the last thing this fn calls, and prevents the folding.
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-#endif
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&)
- PERFTOOLS_THROW
-#ifdef TC_ALIAS
-TC_ALIAS(tc_new_nothrow);
-#else
-{
- void* p = cpp_alloc(size, true);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-#endif
-
-extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_THROW
-#ifdef TC_ALIAS
-TC_ALIAS(tc_free);
-#else
-{
- MallocHook::InvokeDeleteHook(p);
- do_free(p);
-}
-#endif
-
-extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, const std::nothrow_t&) PERFTOOLS_THROW
-#ifdef TC_ALIAS
-TC_ALIAS(tc_free);
-#else
-{
- MallocHook::InvokeDeleteHook(p);
- do_free(p);
-}
-#endif
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align,
- size_t size) PERFTOOLS_THROW {
- void* result = do_memalign_or_cpp_memalign(align, size);
- MallocHook::InvokeNewHook(result, size);
- return result;
-}
-
-extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign(
- void** result_ptr, size_t align, size_t size) PERFTOOLS_THROW {
- if (((align % sizeof(void*)) != 0) ||
- ((align & (align - 1)) != 0) ||
- (align == 0)) {
- return EINVAL;
- }
-
- void* result = do_memalign_or_cpp_memalign(align, size);
- MallocHook::InvokeNewHook(result, size);
- if (UNLIKELY(result == NULL)) {
- return ENOMEM;
- } else {
- *result_ptr = result;
- return 0;
- }
-}
-
-static size_t pagesize = 0;
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) PERFTOOLS_THROW {
- // Allocate page-aligned object of length >= size bytes
- if (pagesize == 0) pagesize = getpagesize();
- void* result = do_memalign_or_cpp_memalign(pagesize, size);
- MallocHook::InvokeNewHook(result, size);
- return result;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) PERFTOOLS_THROW {
- // Round up size to a multiple of pagesize
- if (pagesize == 0) pagesize = getpagesize();
- if (size == 0) { // pvalloc(0) should allocate one page, according to
- size = pagesize; // http://man.free4web.biz/man3/libmpatrol.3.html
- }
- size = (size + pagesize - 1) & ~(pagesize - 1);
- void* result = do_memalign_or_cpp_memalign(pagesize, size);
- MallocHook::InvokeNewHook(result, size);
- return result;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_THROW {
- do_malloc_stats();
-}
-
-extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_THROW {
- return do_mallopt(cmd, value);
-}
-
-#ifdef HAVE_STRUCT_MALLINFO
-extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_THROW {
- return do_mallinfo();
-}
-#endif
-
-extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_THROW {
- return MallocExtension::instance()->GetAllocatedSize(ptr);
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_THROW {
- void* result = do_malloc(size);
- MallocHook::InvokeNewHook(result, size);
- return result;
-}
-
-#endif // TCMALLOC_USING_DEBUGALLOCATION
diff --git a/src/third_party/gperftools-2.5/src/tcmalloc.h b/src/third_party/gperftools-2.5/src/tcmalloc.h
deleted file mode 100644
index 2d64f4eb40b..00000000000
--- a/src/third_party/gperftools-2.5/src/tcmalloc.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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>
-//
-// Some obscure memory-allocation routines may not be declared on all
-// systems. In those cases, we'll just declare them ourselves.
-// This file is meant to be used only internally, for unittests.
-
-#include <config.h>
-
-#ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 600 // for posix_memalign
-#endif
-#include <stdlib.h> // for posix_memalign
-// FreeBSD has malloc.h, but complains if you use it
-#if defined(HAVE_MALLOC_H) && !defined(__FreeBSD__)
-#include <malloc.h> // for memalign, valloc, pvalloc
-#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.
-#ifndef __THROW // I guess we're not on a glibc system
-# define __THROW // __THROW is just an optimization, so ok to make it ""
-#endif
-
-#if !HAVE_CFREE_SYMBOL
-extern "C" void cfree(void* ptr) __THROW;
-#endif
-#if !HAVE_POSIX_MEMALIGN_SYMBOL
-extern "C" int posix_memalign(void** ptr, size_t align, size_t size) __THROW;
-#endif
-#if !HAVE_MEMALIGN_SYMBOL
-extern "C" void* memalign(size_t __alignment, size_t __size) __THROW;
-#endif
-#if !HAVE_VALLOC_SYMBOL
-extern "C" void* valloc(size_t __size) __THROW;
-#endif
-#if !HAVE_PVALLOC_SYMBOL
-extern "C" void* pvalloc(size_t __size) __THROW;
-#endif
diff --git a/src/third_party/gperftools-2.5/src/tcmalloc_guard.h b/src/third_party/gperftools-2.5/src/tcmalloc_guard.h
deleted file mode 100644
index 84952bac2ea..00000000000
--- a/src/third_party/gperftools-2.5/src/tcmalloc_guard.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Craig Silverstein
-//
-// We expose the TCMallocGuard class -- which initializes the tcmalloc
-// allocator -- so classes that need to be sure tcmalloc is loaded
-// before they do stuff -- notably heap-profiler -- can. To use this
-// create a static TCMallocGuard instance at the top of a file where
-// you need tcmalloc to be initialized before global constructors run.
-
-#ifndef TCMALLOC_TCMALLOC_GUARD_H_
-#define TCMALLOC_TCMALLOC_GUARD_H_
-
-class TCMallocGuard {
- public:
- TCMallocGuard();
- ~TCMallocGuard();
-};
-
-#endif // TCMALLOC_TCMALLOC_GUARD_H_
diff --git a/src/third_party/gperftools-2.5/src/third_party/valgrind.h b/src/third_party/gperftools-2.5/src/third_party/valgrind.h
deleted file mode 100644
index 577c59ab0cd..00000000000
--- a/src/third_party/gperftools-2.5/src/third_party/valgrind.h
+++ /dev/null
@@ -1,3924 +0,0 @@
-/* -*- c -*-
- ----------------------------------------------------------------
-
- Notice that the following BSD-style license applies to this one
- file (valgrind.h) only. The rest of Valgrind is licensed under the
- terms of the GNU General Public License, version 2, unless
- otherwise indicated. See the COPYING file in the source
- distribution for details.
-
- ----------------------------------------------------------------
-
- This file is part of Valgrind, a dynamic binary instrumentation
- framework.
-
- Copyright (C) 2000-2008 Julian Seward. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
-
- 3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
- ----------------------------------------------------------------
-
- Notice that the above BSD-style license applies to this one file
- (valgrind.h) only. The entire rest of Valgrind is licensed under
- the terms of the GNU General Public License, version 2. See the
- COPYING file in the source distribution for details.
-
- ----------------------------------------------------------------
-*/
-
-
-/* This file is for inclusion into client (your!) code.
-
- You can use these macros to manipulate and query Valgrind's
- execution inside your own programs.
-
- The resulting executables will still run without Valgrind, just a
- little bit more slowly than they otherwise would, but otherwise
- unchanged. When not running on valgrind, each client request
- consumes very few (eg. 7) instructions, so the resulting performance
- loss is negligible unless you plan to execute client requests
- millions of times per second. Nevertheless, if that is still a
- problem, you can compile with the NVALGRIND symbol defined (gcc
- -DNVALGRIND) so that client requests are not even compiled in. */
-
-#ifndef __VALGRIND_H
-#define __VALGRIND_H
-
-#include <stdarg.h>
-
-/* Nb: this file might be included in a file compiled with -ansi. So
- we can't use C++ style "//" comments nor the "asm" keyword (instead
- use "__asm__"). */
-
-/* Derive some tags indicating what the target platform is. Note
- that in this file we're using the compiler's CPP symbols for
- identifying architectures, which are different to the ones we use
- within the rest of Valgrind. Note, __powerpc__ is active for both
- 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
- latter (on Linux, that is). */
-#undef PLAT_x86_linux
-#undef PLAT_amd64_linux
-#undef PLAT_ppc32_linux
-#undef PLAT_ppc64_linux
-#undef PLAT_ppc32_aix5
-#undef PLAT_ppc64_aix5
-
-#if !defined(_AIX) && defined(__i386__)
-# define PLAT_x86_linux 1
-#elif !defined(_AIX) && defined(__x86_64__)
-# define PLAT_amd64_linux 1
-#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
-# define PLAT_ppc32_linux 1
-#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
-# define PLAT_ppc64_linux 1
-#elif defined(_AIX) && defined(__64BIT__)
-# define PLAT_ppc64_aix5 1
-#elif defined(_AIX) && !defined(__64BIT__)
-# define PLAT_ppc32_aix5 1
-#endif
-
-
-/* If we're not compiling for our target platform, don't generate
- any inline asms. */
-#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
- && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
- && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
-# if !defined(NVALGRIND)
-# define NVALGRIND 1
-# endif
-#endif
-
-
-/* ------------------------------------------------------------------ */
-/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
-/* in here of use to end-users -- skip to the next section. */
-/* ------------------------------------------------------------------ */
-
-#if defined(NVALGRIND)
-
-/* Define NVALGRIND to completely remove the Valgrind magic sequence
- from the compiled code (analogous to NDEBUG's effects on
- assert()) */
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- { \
- (_zzq_rlval) = (_zzq_default); \
- }
-
-#else /* ! NVALGRIND */
-
-/* The following defines the magic code sequences which the JITter
- spots and handles magically. Don't look too closely at them as
- they will rot your brain.
-
- The assembly code sequences for all architectures is in this one
- file. This is because this file must be stand-alone, and we don't
- want to have multiple files.
-
- For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
- value gets put in the return slot, so that everything works when
- this is executed not under Valgrind. Args are passed in a memory
- block, and so there's no intrinsic limit to the number that could
- be passed, but it's currently five.
-
- The macro args are:
- _zzq_rlval result lvalue
- _zzq_default default value (result returned when running on real CPU)
- _zzq_request request code
- _zzq_arg1..5 request params
-
- The other two macros are used to support function wrapping, and are
- a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
- guest's NRADDR pseudo-register and whatever other information is
- needed to safely run the call original from the wrapper: on
- ppc64-linux, the R2 value at the divert point is also needed. This
- information is abstracted into a user-visible type, OrigFn.
-
- VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
- guest, but guarantees that the branch instruction will not be
- redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
- branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
- complete inline asm, since it needs to be combined with more magic
- inline asm stuff to be useful.
-*/
-
-/* ------------------------- x86-linux ------------------------- */
-
-#if defined(PLAT_x86_linux)
-
-typedef
- struct {
- unsigned int nraddr; /* where's the code? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "roll $3, %%edi ; roll $13, %%edi\n\t" \
- "roll $29, %%edi ; roll $19, %%edi\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- { volatile unsigned int _zzq_args[6]; \
- volatile unsigned int _zzq_result; \
- _zzq_args[0] = (unsigned int)(_zzq_request); \
- _zzq_args[1] = (unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int)(_zzq_arg5); \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %EDX = client_request ( %EAX ) */ \
- "xchgl %%ebx,%%ebx" \
- : "=d" (_zzq_result) \
- : "a" (&_zzq_args[0]), "0" (_zzq_default) \
- : "cc", "memory" \
- ); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- volatile unsigned int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %EAX = guest_NRADDR */ \
- "xchgl %%ecx,%%ecx" \
- : "=a" (__addr) \
- : \
- : "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- }
-
-#define VALGRIND_CALL_NOREDIR_EAX \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* call-noredir *%EAX */ \
- "xchgl %%edx,%%edx\n\t"
-#endif /* PLAT_x86_linux */
-
-/* ------------------------ amd64-linux ------------------------ */
-
-#if defined(PLAT_amd64_linux)
-
-typedef
- struct {
- unsigned long long int nraddr; /* where's the code? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
- "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- { volatile unsigned long long int _zzq_args[6]; \
- volatile unsigned long long int _zzq_result; \
- _zzq_args[0] = (unsigned long long int)(_zzq_request); \
- _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %RDX = client_request ( %RAX ) */ \
- "xchgq %%rbx,%%rbx" \
- : "=d" (_zzq_result) \
- : "a" (&_zzq_args[0]), "0" (_zzq_default) \
- : "cc", "memory" \
- ); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- volatile unsigned long long int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %RAX = guest_NRADDR */ \
- "xchgq %%rcx,%%rcx" \
- : "=a" (__addr) \
- : \
- : "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- }
-
-#define VALGRIND_CALL_NOREDIR_RAX \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* call-noredir *%RAX */ \
- "xchgq %%rdx,%%rdx\n\t"
-#endif /* PLAT_amd64_linux */
-
-/* ------------------------ ppc32-linux ------------------------ */
-
-#if defined(PLAT_ppc32_linux)
-
-typedef
- struct {
- unsigned int nraddr; /* where's the code? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
- "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- \
- { unsigned int _zzq_args[6]; \
- unsigned int _zzq_result; \
- unsigned int* _zzq_ptr; \
- _zzq_args[0] = (unsigned int)(_zzq_request); \
- _zzq_args[1] = (unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int)(_zzq_arg5); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile("mr 3,%1\n\t" /*default*/ \
- "mr 4,%2\n\t" /*ptr*/ \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1\n\t" \
- "mr %0,3" /*result*/ \
- : "=b" (_zzq_result) \
- : "b" (_zzq_default), "b" (_zzq_ptr) \
- : "cc", "memory", "r3", "r4"); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- unsigned int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR */ \
- "or 2,2,2\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "cc", "memory", "r3" \
- ); \
- _zzq_orig->nraddr = __addr; \
- }
-
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
- "or 3,3,3\n\t"
-#endif /* PLAT_ppc32_linux */
-
-/* ------------------------ ppc64-linux ------------------------ */
-
-#if defined(PLAT_ppc64_linux)
-
-typedef
- struct {
- unsigned long long int nraddr; /* where's the code? */
- unsigned long long int r2; /* what tocptr do we need? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
- "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- \
- { unsigned long long int _zzq_args[6]; \
- register unsigned long long int _zzq_result __asm__("r3"); \
- register unsigned long long int* _zzq_ptr __asm__("r4"); \
- _zzq_args[0] = (unsigned long long int)(_zzq_request); \
- _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1" \
- : "=r" (_zzq_result) \
- : "0" (_zzq_default), "r" (_zzq_ptr) \
- : "cc", "memory"); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- register unsigned long long int __addr __asm__("r3"); \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR */ \
- "or 2,2,2" \
- : "=r" (__addr) \
- : \
- : "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR_GPR2 */ \
- "or 4,4,4" \
- : "=r" (__addr) \
- : \
- : "cc", "memory" \
- ); \
- _zzq_orig->r2 = __addr; \
- }
-
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
- "or 3,3,3\n\t"
-
-#endif /* PLAT_ppc64_linux */
-
-/* ------------------------ ppc32-aix5 ------------------------- */
-
-#if defined(PLAT_ppc32_aix5)
-
-typedef
- struct {
- unsigned int nraddr; /* where's the code? */
- unsigned int r2; /* what tocptr do we need? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
- "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- \
- { unsigned int _zzq_args[7]; \
- register unsigned int _zzq_result; \
- register unsigned int* _zzq_ptr; \
- _zzq_args[0] = (unsigned int)(_zzq_request); \
- _zzq_args[1] = (unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int)(_zzq_arg5); \
- _zzq_args[6] = (unsigned int)(_zzq_default); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile("mr 4,%1\n\t" \
- "lwz 3, 24(4)\n\t" \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1\n\t" \
- "mr %0,3" \
- : "=b" (_zzq_result) \
- : "b" (_zzq_ptr) \
- : "r3", "r4", "cc", "memory"); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- register unsigned int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR */ \
- "or 2,2,2\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "r3", "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR_GPR2 */ \
- "or 4,4,4\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "r3", "cc", "memory" \
- ); \
- _zzq_orig->r2 = __addr; \
- }
-
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
- "or 3,3,3\n\t"
-
-#endif /* PLAT_ppc32_aix5 */
-
-/* ------------------------ ppc64-aix5 ------------------------- */
-
-#if defined(PLAT_ppc64_aix5)
-
-typedef
- struct {
- unsigned long long int nraddr; /* where's the code? */
- unsigned long long int r2; /* what tocptr do we need? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
- "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- \
- { unsigned long long int _zzq_args[7]; \
- register unsigned long long int _zzq_result; \
- register unsigned long long int* _zzq_ptr; \
- _zzq_args[0] = (unsigned int long long)(_zzq_request); \
- _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
- _zzq_args[6] = (unsigned int long long)(_zzq_default); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile("mr 4,%1\n\t" \
- "ld 3, 48(4)\n\t" \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1\n\t" \
- "mr %0,3" \
- : "=b" (_zzq_result) \
- : "b" (_zzq_ptr) \
- : "r3", "r4", "cc", "memory"); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- register unsigned long long int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR */ \
- "or 2,2,2\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "r3", "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR_GPR2 */ \
- "or 4,4,4\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "r3", "cc", "memory" \
- ); \
- _zzq_orig->r2 = __addr; \
- }
-
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
- "or 3,3,3\n\t"
-
-#endif /* PLAT_ppc64_aix5 */
-
-/* Insert assembly code for other platforms here... */
-
-#endif /* NVALGRIND */
-
-
-/* ------------------------------------------------------------------ */
-/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
-/* ugly. It's the least-worst tradeoff I can think of. */
-/* ------------------------------------------------------------------ */
-
-/* This section defines magic (a.k.a appalling-hack) macros for doing
- guaranteed-no-redirection macros, so as to get from function
- wrappers to the functions they are wrapping. The whole point is to
- construct standard call sequences, but to do the call itself with a
- special no-redirect call pseudo-instruction that the JIT
- understands and handles specially. This section is long and
- repetitious, and I can't see a way to make it shorter.
-
- The naming scheme is as follows:
-
- CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
-
- 'W' stands for "word" and 'v' for "void". Hence there are
- different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
- and for each, the possibility of returning a word-typed result, or
- no result.
-*/
-
-/* Use these to write the name of your wrapper. NOTE: duplicates
- VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
-
-#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
- _vgwZU_##soname##_##fnname
-
-#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
- _vgwZZ_##soname##_##fnname
-
-/* Use this macro from within a wrapper function to collect the
- context (address and possibly other info) of the original function.
- Once you have that you can then use it in one of the CALL_FN_
- macros. The type of the argument _lval is OrigFn. */
-#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
-
-/* Derivatives of the main macros below, for calling functions
- returning void. */
-
-#define CALL_FN_v_v(fnptr) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_v(_junk,fnptr); } while (0)
-
-#define CALL_FN_v_W(fnptr, arg1) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
-
-#define CALL_FN_v_WW(fnptr, arg1,arg2) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
-
-#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
-
-/* ------------------------- x86-linux ------------------------- */
-
-#if defined(PLAT_x86_linux)
-
-/* These regs are trashed by the hidden call. No need to mention eax
- as gcc can already see that, plus causes gcc to bomb. */
-#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
-
-/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
- long) == 4. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[1]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[2]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- __asm__ volatile( \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $4, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- __asm__ volatile( \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $8, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[4]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- __asm__ volatile( \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $12, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[5]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- __asm__ volatile( \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $16, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[6]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- __asm__ volatile( \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $20, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[7]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- __asm__ volatile( \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $24, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[8]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- __asm__ volatile( \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $28, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[9]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- __asm__ volatile( \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $32, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[10]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- __asm__ volatile( \
- "pushl 36(%%eax)\n\t" \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $36, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[11]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- __asm__ volatile( \
- "pushl 40(%%eax)\n\t" \
- "pushl 36(%%eax)\n\t" \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $40, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
- arg6,arg7,arg8,arg9,arg10, \
- arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[12]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- __asm__ volatile( \
- "pushl 44(%%eax)\n\t" \
- "pushl 40(%%eax)\n\t" \
- "pushl 36(%%eax)\n\t" \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $44, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
- arg6,arg7,arg8,arg9,arg10, \
- arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[13]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- _argvec[12] = (unsigned long)(arg12); \
- __asm__ volatile( \
- "pushl 48(%%eax)\n\t" \
- "pushl 44(%%eax)\n\t" \
- "pushl 40(%%eax)\n\t" \
- "pushl 36(%%eax)\n\t" \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $48, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_x86_linux */
-
-/* ------------------------ amd64-linux ------------------------ */
-
-#if defined(PLAT_amd64_linux)
-
-/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
- "rdi", "r8", "r9", "r10", "r11"
-
-/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
- long) == 8. */
-
-/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
- macros. In order not to trash the stack redzone, we need to drop
- %rsp by 128 before the hidden call, and restore afterwards. The
- nastyness is that it is only by luck that the stack still appears
- to be unwindable during the hidden call - since then the behaviour
- of any routine using this macro does not match what the CFI data
- says. Sigh.
-
- Why is this important? Imagine that a wrapper has a stack
- allocated local, and passes to the hidden call, a pointer to it.
- Because gcc does not know about the hidden call, it may allocate
- that local in the redzone. Unfortunately the hidden call may then
- trash it before it comes to use it. So we must step clear of the
- redzone, for the duration of the hidden call, to make it safe.
-
- Probably the same problem afflicts the other redzone-style ABIs too
- (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
- self describing (none of this CFI nonsense) so at least messing
- with the stack pointer doesn't give a danger of non-unwindable
- stack. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[1]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[2]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[4]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[5]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[6]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[7]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- "addq $128,%%rsp\n\t" \
- VALGRIND_CALL_NOREDIR_RAX \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[8]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $8, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[9]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $16, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[10]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $24, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[11]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 80(%%rax)\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $32, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[12]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 88(%%rax)\n\t" \
- "pushq 80(%%rax)\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $40, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[13]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- _argvec[12] = (unsigned long)(arg12); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 96(%%rax)\n\t" \
- "pushq 88(%%rax)\n\t" \
- "pushq 80(%%rax)\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $48, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_amd64_linux */
-
-/* ------------------------ ppc32-linux ------------------------ */
-
-#if defined(PLAT_ppc32_linux)
-
-/* This is useful for finding out about the on-stack stuff:
-
- extern int f9 ( int,int,int,int,int,int,int,int,int );
- extern int f10 ( int,int,int,int,int,int,int,int,int,int );
- extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
- extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
-
- int g9 ( void ) {
- return f9(11,22,33,44,55,66,77,88,99);
- }
- int g10 ( void ) {
- return f10(11,22,33,44,55,66,77,88,99,110);
- }
- int g11 ( void ) {
- return f11(11,22,33,44,55,66,77,88,99,110,121);
- }
- int g12 ( void ) {
- return f12(11,22,33,44,55,66,77,88,99,110,121,132);
- }
-*/
-
-/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS \
- "lr", "ctr", "xer", \
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
- "r11", "r12", "r13"
-
-/* These CALL_FN_ macros assume that on ppc32-linux,
- sizeof(unsigned long) == 4. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[1]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[2]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[4]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[5]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[6]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[7]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[8]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[9]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[10]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- _argvec[9] = (unsigned long)arg9; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "addi 1,1,-16\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,8(1)\n\t" \
- /* args1-8 */ \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,16\n\t" \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[11]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- _argvec[9] = (unsigned long)arg9; \
- _argvec[10] = (unsigned long)arg10; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "addi 1,1,-16\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,12(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,8(1)\n\t" \
- /* args1-8 */ \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,16\n\t" \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[12]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- _argvec[9] = (unsigned long)arg9; \
- _argvec[10] = (unsigned long)arg10; \
- _argvec[11] = (unsigned long)arg11; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "addi 1,1,-32\n\t" \
- /* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,16(1)\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,12(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,8(1)\n\t" \
- /* args1-8 */ \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,32\n\t" \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[13]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- _argvec[9] = (unsigned long)arg9; \
- _argvec[10] = (unsigned long)arg10; \
- _argvec[11] = (unsigned long)arg11; \
- _argvec[12] = (unsigned long)arg12; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "addi 1,1,-32\n\t" \
- /* arg12 */ \
- "lwz 3,48(11)\n\t" \
- "stw 3,20(1)\n\t" \
- /* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,16(1)\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,12(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,8(1)\n\t" \
- /* args1-8 */ \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,32\n\t" \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_ppc32_linux */
-
-/* ------------------------ ppc64-linux ------------------------ */
-
-#if defined(PLAT_ppc64_linux)
-
-/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS \
- "lr", "ctr", "xer", \
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
- "r11", "r12", "r13"
-
-/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
- long) == 8. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+0]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+1]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+2]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+3]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+4]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+5]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+6]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+7]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+8]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+9]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "addi 1,1,-128\n\t" /* expand stack frame */ \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,128" /* restore frame */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+10]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "addi 1,1,-128\n\t" /* expand stack frame */ \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,128" /* restore frame */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+11]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "addi 1,1,-144\n\t" /* expand stack frame */ \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,144" /* restore frame */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+12]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- _argvec[2+12] = (unsigned long)arg12; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "addi 1,1,-144\n\t" /* expand stack frame */ \
- /* arg12 */ \
- "ld 3,96(11)\n\t" \
- "std 3,136(1)\n\t" \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,144" /* restore frame */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_ppc64_linux */
-
-/* ------------------------ ppc32-aix5 ------------------------- */
-
-#if defined(PLAT_ppc32_aix5)
-
-/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS \
- "lr", "ctr", "xer", \
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
- "r11", "r12", "r13"
-
-/* Expand the stack frame, copying enough info that unwinding
- still works. Trashes r3. */
-
-#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
- "addi 1,1,-" #_n_fr "\n\t" \
- "lwz 3," #_n_fr "(1)\n\t" \
- "stw 3,0(1)\n\t"
-
-#define VG_CONTRACT_FRAME_BY(_n_fr) \
- "addi 1,1," #_n_fr "\n\t"
-
-/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
- long) == 4. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+0]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+1]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+2]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+3]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+4]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+5]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+6]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+7]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+8]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+9]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(64) \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
- /* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(64) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+10]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(64) \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,60(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
- /* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(64) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+11]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(72) \
- /* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,64(1)\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,60(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
- /* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(72) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+12]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- _argvec[2+12] = (unsigned long)arg12; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(72) \
- /* arg12 */ \
- "lwz 3,48(11)\n\t" \
- "stw 3,68(1)\n\t" \
- /* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,64(1)\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,60(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
- /* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(72) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_ppc32_aix5 */
-
-/* ------------------------ ppc64-aix5 ------------------------- */
-
-#if defined(PLAT_ppc64_aix5)
-
-/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS \
- "lr", "ctr", "xer", \
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
- "r11", "r12", "r13"
-
-/* Expand the stack frame, copying enough info that unwinding
- still works. Trashes r3. */
-
-#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
- "addi 1,1,-" #_n_fr "\n\t" \
- "ld 3," #_n_fr "(1)\n\t" \
- "std 3,0(1)\n\t"
-
-#define VG_CONTRACT_FRAME_BY(_n_fr) \
- "addi 1,1," #_n_fr "\n\t"
-
-/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
- long) == 8. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+0]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+1]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+2]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+3]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+4]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+5]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+6]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+7]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+8]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+9]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(128) \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(128) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+10]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(128) \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(128) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+11]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(144) \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(144) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+12]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- _argvec[2+12] = (unsigned long)arg12; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(144) \
- /* arg12 */ \
- "ld 3,96(11)\n\t" \
- "std 3,136(1)\n\t" \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(144) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_ppc64_aix5 */
-
-
-/* ------------------------------------------------------------------ */
-/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
-/* */
-/* ------------------------------------------------------------------ */
-
-/* Some request codes. There are many more of these, but most are not
- exposed to end-user view. These are the public ones, all of the
- form 0x1000 + small_number.
-
- Core ones are in the range 0x00000000--0x0000ffff. The non-public
- ones start at 0x2000.
-*/
-
-/* These macros are used by tools -- they must be public, but don't
- embed them into other programs. */
-#define VG_USERREQ_TOOL_BASE(a,b) \
- ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
-#define VG_IS_TOOL_USERREQ(a, b, v) \
- (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
-
-/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
- This enum comprises an ABI exported by Valgrind to programs
- which use client requests. DO NOT CHANGE THE ORDER OF THESE
- ENTRIES, NOR DELETE ANY -- add new ones at the end. */
-typedef
- enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
- VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
-
- /* These allow any function to be called from the simulated
- CPU but run on the real CPU. Nb: the first arg passed to
- the function is always the ThreadId of the running
- thread! So CLIENT_CALL0 actually requires a 1 arg
- function, etc. */
- VG_USERREQ__CLIENT_CALL0 = 0x1101,
- VG_USERREQ__CLIENT_CALL1 = 0x1102,
- VG_USERREQ__CLIENT_CALL2 = 0x1103,
- VG_USERREQ__CLIENT_CALL3 = 0x1104,
-
- /* Can be useful in regression testing suites -- eg. can
- send Valgrind's output to /dev/null and still count
- errors. */
- VG_USERREQ__COUNT_ERRORS = 0x1201,
-
- /* These are useful and can be interpreted by any tool that
- tracks malloc() et al, by using vg_replace_malloc.c. */
- VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
- VG_USERREQ__FREELIKE_BLOCK = 0x1302,
- /* Memory pool support. */
- VG_USERREQ__CREATE_MEMPOOL = 0x1303,
- VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
- VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
- VG_USERREQ__MEMPOOL_FREE = 0x1306,
- VG_USERREQ__MEMPOOL_TRIM = 0x1307,
- VG_USERREQ__MOVE_MEMPOOL = 0x1308,
- VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
- VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
-
- /* Allow printfs to valgrind log. */
- VG_USERREQ__PRINTF = 0x1401,
- VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
-
- /* Stack support. */
- VG_USERREQ__STACK_REGISTER = 0x1501,
- VG_USERREQ__STACK_DEREGISTER = 0x1502,
- VG_USERREQ__STACK_CHANGE = 0x1503
- } Vg_ClientRequest;
-
-#if !defined(__GNUC__)
-# define __extension__ /* */
-#endif
-
-/* Returns the number of Valgrinds this code is running under. That
- is, 0 if running natively, 1 if running under Valgrind, 2 if
- running under Valgrind which is running under another Valgrind,
- etc. */
-#define RUNNING_ON_VALGRIND __extension__ \
- ({unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
- VG_USERREQ__RUNNING_ON_VALGRIND, \
- 0, 0, 0, 0, 0); \
- _qzz_res; \
- })
-
-
-/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
- _qzz_len - 1]. Useful if you are debugging a JITter or some such,
- since it provides a way to make sure valgrind will retranslate the
- invalidated area. Returns no value. */
-#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DISCARD_TRANSLATIONS, \
- _qzz_addr, _qzz_len, 0, 0, 0); \
- }
-
-
-/* These requests are for getting Valgrind itself to print something.
- Possibly with a backtrace. This is a really ugly hack. */
-
-#if defined(NVALGRIND)
-
-# define VALGRIND_PRINTF(...)
-# define VALGRIND_PRINTF_BACKTRACE(...)
-
-#else /* NVALGRIND */
-
-/* Modern GCC will optimize the static routine out if unused,
- and unused attribute will shut down warnings about it. */
-static int VALGRIND_PRINTF(const char *format, ...)
- __attribute__((format(__printf__, 1, 2), __unused__));
-static int
-VALGRIND_PRINTF(const char *format, ...)
-{
- unsigned long _qzz_res;
- va_list vargs;
- va_start(vargs, format);
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
- (unsigned long)format, (unsigned long)vargs,
- 0, 0, 0);
- va_end(vargs);
- return (int)_qzz_res;
-}
-
-static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
- __attribute__((format(__printf__, 1, 2), __unused__));
-static int
-VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
-{
- unsigned long _qzz_res;
- va_list vargs;
- va_start(vargs, format);
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
- (unsigned long)format, (unsigned long)vargs,
- 0, 0, 0);
- va_end(vargs);
- return (int)_qzz_res;
-}
-
-#endif /* NVALGRIND */
-
-
-/* These requests allow control to move from the simulated CPU to the
- real CPU, calling an arbitary function.
-
- Note that the current ThreadId is inserted as the first argument.
- So this call:
-
- VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
-
- requires f to have this signature:
-
- Word f(Word tid, Word arg1, Word arg2)
-
- where "Word" is a word-sized type.
-
- Note that these client requests are not entirely reliable. For example,
- if you call a function with them that subsequently calls printf(),
- there's a high chance Valgrind will crash. Generally, your prospects of
- these working are made higher if the called function does not refer to
- any global variables, and does not refer to any libc or other functions
- (printf et al). Any kind of entanglement with libc or dynamic linking is
- likely to have a bad outcome, for tricky reasons which we've grappled
- with a lot in the past.
-*/
-#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL0, \
- _qyy_fn, \
- 0, 0, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL1, \
- _qyy_fn, \
- _qyy_arg1, 0, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL2, \
- _qyy_fn, \
- _qyy_arg1, _qyy_arg2, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL3, \
- _qyy_fn, \
- _qyy_arg1, _qyy_arg2, \
- _qyy_arg3, 0); \
- _qyy_res; \
- })
-
-
-/* Counts the number of errors that have been recorded by a tool. Nb:
- the tool must record the errors with VG_(maybe_record_error)() or
- VG_(unique_error)() for them to be counted. */
-#define VALGRIND_COUNT_ERRORS \
- __extension__ \
- ({unsigned int _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__COUNT_ERRORS, \
- 0, 0, 0, 0, 0); \
- _qyy_res; \
- })
-
-/* Mark a block of memory as having been allocated by a malloc()-like
- function. `addr' is the start of the usable block (ie. after any
- redzone) `rzB' is redzone size if the allocator can apply redzones;
- use '0' if not. Adding redzones makes it more likely Valgrind will spot
- block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
- for calloc(). Put it immediately after the point where a block is
- allocated.
-
- If you're using Memcheck: If you're allocating memory via superblocks,
- and then handing out small chunks of each superblock, if you don't have
- redzones on your small blocks, it's worth marking the superblock with
- VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
- detected. But if you can put redzones on, it's probably better to not do
- this, so that messages for small overruns are described in terms of the
- small block rather than the superblock (but if you have a big overrun
- that skips over a redzone, you could miss an error this way). See
- memcheck/tests/custom_alloc.c for an example.
-
- WARNING: if your allocator uses malloc() or 'new' to allocate
- superblocks, rather than mmap() or brk(), this will not work properly --
- you'll likely get assertion failures during leak detection. This is
- because Valgrind doesn't like seeing overlapping heap blocks. Sorry.
-
- Nb: block must be freed via a free()-like function specified
- with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
-#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MALLOCLIKE_BLOCK, \
- addr, sizeB, rzB, is_zeroed, 0); \
- }
-
-/* Mark a block of memory as having been freed by a free()-like function.
- `rzB' is redzone size; it must match that given to
- VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
- checker. Put it immediately after the point where the block is freed. */
-#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__FREELIKE_BLOCK, \
- addr, rzB, 0, 0, 0); \
- }
-
-/* Create a memory pool. */
-#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__CREATE_MEMPOOL, \
- pool, rzB, is_zeroed, 0, 0); \
- }
-
-/* Destroy a memory pool. */
-#define VALGRIND_DESTROY_MEMPOOL(pool) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DESTROY_MEMPOOL, \
- pool, 0, 0, 0, 0); \
- }
-
-/* Associate a piece of memory with a memory pool. */
-#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_ALLOC, \
- pool, addr, size, 0, 0); \
- }
-
-/* Disassociate a piece of memory from a memory pool. */
-#define VALGRIND_MEMPOOL_FREE(pool, addr) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_FREE, \
- pool, addr, 0, 0, 0); \
- }
-
-/* Disassociate any pieces outside a particular range. */
-#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_TRIM, \
- pool, addr, size, 0, 0); \
- }
-
-/* Resize and/or move a piece associated with a memory pool. */
-#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MOVE_MEMPOOL, \
- poolA, poolB, 0, 0, 0); \
- }
-
-/* Resize and/or move a piece associated with a memory pool. */
-#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_CHANGE, \
- pool, addrA, addrB, size, 0); \
- }
-
-/* Return 1 if a mempool exists, else 0. */
-#define VALGRIND_MEMPOOL_EXISTS(pool) \
- ({unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_EXISTS, \
- pool, 0, 0, 0, 0); \
- _qzz_res; \
- })
-
-/* Mark a piece of memory as being a stack. Returns a stack id. */
-#define VALGRIND_STACK_REGISTER(start, end) \
- ({unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__STACK_REGISTER, \
- start, end, 0, 0, 0); \
- _qzz_res; \
- })
-
-/* Unmark the piece of memory associated with a stack id as being a
- stack. */
-#define VALGRIND_STACK_DEREGISTER(id) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__STACK_DEREGISTER, \
- id, 0, 0, 0, 0); \
- }
-
-/* Change the start and end address of the stack id. */
-#define VALGRIND_STACK_CHANGE(id, start, end) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__STACK_CHANGE, \
- id, start, end, 0, 0); \
- }
-
-
-#undef PLAT_x86_linux
-#undef PLAT_amd64_linux
-#undef PLAT_ppc32_linux
-#undef PLAT_ppc64_linux
-#undef PLAT_ppc32_aix5
-#undef PLAT_ppc64_aix5
-
-#endif /* __VALGRIND_H */
diff --git a/src/third_party/gperftools-2.5/src/thread_cache.cc b/src/third_party/gperftools-2.5/src/thread_cache.cc
deleted file mode 100644
index bd2d66f9fa2..00000000000
--- a/src/third_party/gperftools-2.5/src/thread_cache.cc
+++ /dev/null
@@ -1,508 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Ken Ashcraft <opensource@google.com>
-
-#include <config.h>
-#include "thread_cache.h"
-#include <errno.h>
-#include <string.h> // for memcpy
-#include <algorithm> // for max, min
-#include "base/commandlineflags.h" // for SpinLockHolder
-#include "base/spinlock.h" // for SpinLockHolder
-#include "getenv_safe.h" // for TCMallocGetenvSafe
-#include "central_freelist.h" // for CentralFreeListPadded
-#include "maybe_threads.h"
-
-using std::min;
-using std::max;
-
-// Note: this is initialized manually in InitModule to ensure that
-// it's configured at right time
-//
-// 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. "
-// "Maximum value of this flag is capped to 1 GB.");
-
-
-namespace tcmalloc {
-
-static bool phinited = false;
-
-volatile size_t ThreadCache::per_thread_cache_size_ = kMaxThreadCacheSize;
-size_t ThreadCache::overall_thread_cache_size_ = kDefaultOverallThreadCacheSize;
-ssize_t ThreadCache::unclaimed_cache_space_ = kDefaultOverallThreadCacheSize;
-PageHeapAllocator<ThreadCache> threadcache_allocator;
-ThreadCache* ThreadCache::thread_heaps_ = NULL;
-int ThreadCache::thread_heap_count_ = 0;
-ThreadCache* ThreadCache::next_memory_steal_ = NULL;
-#ifdef HAVE_TLS
-__thread ThreadCache::ThreadLocalData ThreadCache::threadlocal_data_
- ATTR_INITIAL_EXEC
- = {0, 0};
-#endif
-bool ThreadCache::tsd_inited_ = false;
-pthread_key_t ThreadCache::heap_key_;
-
-void ThreadCache::Init(pthread_t tid) {
- size_ = 0;
-
- max_size_ = 0;
- IncreaseCacheLimitLocked();
- if (max_size_ == 0) {
- // There isn't enough memory to go around. Just give the minimum to
- // this thread.
- max_size_ = kMinThreadCacheSize;
-
- // Take unclaimed_cache_space_ negative.
- unclaimed_cache_space_ -= kMinThreadCacheSize;
- ASSERT(unclaimed_cache_space_ < 0);
- }
-
- next_ = NULL;
- prev_ = NULL;
- tid_ = tid;
- in_setspecific_ = false;
- for (size_t cl = 0; cl < kNumClasses; ++cl) {
- list_[cl].Init();
- }
-
- uint32_t sampler_seed;
- memcpy(&sampler_seed, &tid, sizeof(sampler_seed));
- sampler_.Init(sampler_seed);
-}
-
-void ThreadCache::Cleanup() {
- // Put unused memory back into central cache
- for (int cl = 0; cl < kNumClasses; ++cl) {
- if (list_[cl].length() > 0) {
- ReleaseToCentralCache(&list_[cl], cl, list_[cl].length());
- }
- }
-}
-
-// Remove some objects of class "cl" from central cache and add to thread heap.
-// On success, return the first object for immediate use; otherwise return NULL.
-void* ThreadCache::FetchFromCentralCache(size_t cl, size_t byte_size) {
- FreeList* list = &list_[cl];
- ASSERT(list->empty());
- const int batch_size = Static::sizemap()->num_objects_to_move(cl);
-
- const int num_to_move = min<int>(list->max_length(), batch_size);
- void *start, *end;
- int fetch_count = Static::central_cache()[cl].RemoveRange(
- &start, &end, num_to_move);
-
- ASSERT((start == NULL) == (fetch_count == 0));
- if (--fetch_count >= 0) {
- size_ += byte_size * fetch_count;
- list->PushRange(fetch_count, SLL_Next(start), end);
- }
-
- // Increase max length slowly up to batch_size. After that,
- // increase by batch_size in one shot so that the length is a
- // multiple of batch_size.
- if (list->max_length() < batch_size) {
- list->set_max_length(list->max_length() + 1);
- } else {
- // Don't let the list get too long. In 32 bit builds, the length
- // is represented by a 16 bit int, so we need to watch out for
- // integer overflow.
- int new_length = min<int>(list->max_length() + batch_size,
- kMaxDynamicFreeListLength);
- // The list's max_length must always be a multiple of batch_size,
- // and kMaxDynamicFreeListLength is not necessarily a multiple
- // of batch_size.
- new_length -= new_length % batch_size;
- ASSERT(new_length % batch_size == 0);
- list->set_max_length(new_length);
- }
- return start;
-}
-
-void ThreadCache::ListTooLong(FreeList* list, size_t cl) {
- const int batch_size = Static::sizemap()->num_objects_to_move(cl);
- ReleaseToCentralCache(list, cl, batch_size);
-
- // If the list is too long, we need to transfer some number of
- // objects to the central cache. Ideally, we would transfer
- // num_objects_to_move, so the code below tries to make max_length
- // converge on num_objects_to_move.
-
- if (list->max_length() < batch_size) {
- // Slow start the max_length so we don't overreserve.
- list->set_max_length(list->max_length() + 1);
- } else if (list->max_length() > batch_size) {
- // If we consistently go over max_length, shrink max_length. If we don't
- // shrink it, some amount of memory will always stay in this freelist.
- list->set_length_overages(list->length_overages() + 1);
- if (list->length_overages() > kMaxOverages) {
- ASSERT(list->max_length() > batch_size);
- list->set_max_length(list->max_length() - batch_size);
- list->set_length_overages(0);
- }
- }
-}
-
-// Remove some objects of class "cl" from thread heap and add to central cache
-void ThreadCache::ReleaseToCentralCache(FreeList* src, size_t cl, int N) {
- ASSERT(src == &list_[cl]);
- if (N > src->length()) N = src->length();
- size_t delta_bytes = N * Static::sizemap()->ByteSizeForClass(cl);
-
- // We return prepackaged chains of the correct size to the central cache.
- // TODO: Use the same format internally in the thread caches?
- int batch_size = Static::sizemap()->num_objects_to_move(cl);
- while (N > batch_size) {
- void *tail, *head;
- src->PopRange(batch_size, &head, &tail);
- Static::central_cache()[cl].InsertRange(head, tail, batch_size);
- N -= batch_size;
- }
- void *tail, *head;
- src->PopRange(N, &head, &tail);
- Static::central_cache()[cl].InsertRange(head, tail, N);
- size_ -= delta_bytes;
-}
-
-// Release idle memory to the central cache
-void ThreadCache::Scavenge() {
- // If the low-water mark for the free list is L, it means we would
- // not have had to allocate anything from the central cache even if
- // we had reduced the free list size by L. We aim to get closer to
- // that situation by dropping L/2 nodes from the free list. This
- // may not release much memory, but if so we will call scavenge again
- // pretty soon and the low-water marks will be high on that call.
- for (int cl = 0; cl < kNumClasses; cl++) {
- FreeList* list = &list_[cl];
- const int lowmark = list->lowwatermark();
- if (lowmark > 0) {
- const int drop = (lowmark > 1) ? lowmark/2 : 1;
- ReleaseToCentralCache(list, cl, drop);
-
- // Shrink the max length if it isn't used. Only shrink down to
- // batch_size -- if the thread was active enough to get the max_length
- // above batch_size, it will likely be that active again. If
- // max_length shinks below batch_size, the thread will have to
- // go through the slow-start behavior again. The slow-start is useful
- // mainly for threads that stay relatively idle for their entire
- // lifetime.
- const int batch_size = Static::sizemap()->num_objects_to_move(cl);
- if (list->max_length() > batch_size) {
- list->set_max_length(
- max<int>(list->max_length() - batch_size, batch_size));
- }
- }
- list->clear_lowwatermark();
- }
-
- IncreaseCacheLimit();
-}
-
-void ThreadCache::IncreaseCacheLimit() {
- SpinLockHolder h(Static::pageheap_lock());
- IncreaseCacheLimitLocked();
-}
-
-void ThreadCache::IncreaseCacheLimitLocked() {
- if (unclaimed_cache_space_ > 0) {
- // Possibly make unclaimed_cache_space_ negative.
- unclaimed_cache_space_ -= kStealAmount;
- max_size_ += kStealAmount;
- return;
- }
- // Don't hold pageheap_lock too long. Try to steal from 10 other
- // threads before giving up. The i < 10 condition also prevents an
- // infinite loop in case none of the existing thread heaps are
- // suitable places to steal from.
- for (int i = 0; i < 10;
- ++i, next_memory_steal_ = next_memory_steal_->next_) {
- // Reached the end of the linked list. Start at the beginning.
- if (next_memory_steal_ == NULL) {
- ASSERT(thread_heaps_ != NULL);
- next_memory_steal_ = thread_heaps_;
- }
- if (next_memory_steal_ == this ||
- next_memory_steal_->max_size_ <= kMinThreadCacheSize) {
- continue;
- }
- next_memory_steal_->max_size_ -= kStealAmount;
- max_size_ += kStealAmount;
-
- next_memory_steal_ = next_memory_steal_->next_;
- return;
- }
-}
-
-int ThreadCache::GetSamplePeriod() {
- return sampler_.GetSamplePeriod();
-}
-
-void ThreadCache::InitModule() {
- SpinLockHolder h(Static::pageheap_lock());
- if (!phinited) {
- const char *tcb = TCMallocGetenvSafe("TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES");
- if (tcb) {
- set_overall_thread_cache_size(strtoll(tcb, NULL, 10));
- }
- Static::InitStaticVars();
- threadcache_allocator.Init();
- phinited = 1;
- }
-}
-
-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() {
- // Initialize per-thread data if necessary
- ThreadCache* heap = NULL;
- {
- SpinLockHolder h(Static::pageheap_lock());
- // 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
- // and added to the linked list. So we search for that first.
- for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) {
- if (h->tid_ == me) {
- heap = h;
- break;
- }
- }
-
- if (heap == NULL) heap = NewHeap(me);
- }
-
- // We call pthread_setspecific() outside the lock because it may
- // call malloc() recursively. We check for the recursive call using
- // the "in_setspecific_" flag so that we can avoid calling
- // pthread_setspecific() if we are already inside pthread_setspecific().
- if (!heap->in_setspecific_ && tsd_inited_) {
- heap->in_setspecific_ = true;
- perftools_pthread_setspecific(heap_key_, heap);
-#ifdef HAVE_TLS
- // Also keep a copy in __thread for faster retrieval
- threadlocal_data_.heap = heap;
- SetMinSizeForSlowPath(kMaxSize + 1);
-#endif
- heap->in_setspecific_ = false;
- }
- return heap;
-}
-
-ThreadCache* ThreadCache::NewHeap(pthread_t tid) {
- // Create the heap and add it to the linked list
- ThreadCache *heap = threadcache_allocator.New();
- heap->Init(tid);
- heap->next_ = thread_heaps_;
- heap->prev_ = NULL;
- if (thread_heaps_ != NULL) {
- thread_heaps_->prev_ = heap;
- } else {
- // This is the only thread heap at the momment.
- ASSERT(next_memory_steal_ == NULL);
- next_memory_steal_ = heap;
- }
- thread_heaps_ = heap;
- thread_heap_count_++;
- return heap;
-}
-
-void ThreadCache::BecomeIdle() {
- if (!tsd_inited_) return; // No caches yet
- ThreadCache* heap = GetThreadHeap();
- if (heap == NULL) return; // No thread cache to remove
- if (heap->in_setspecific_) return; // Do not disturb the active caller
-
- heap->in_setspecific_ = true;
- perftools_pthread_setspecific(heap_key_, NULL);
-#ifdef HAVE_TLS
- // Also update the copy in __thread
- threadlocal_data_.heap = NULL;
- SetMinSizeForSlowPath(0);
-#endif
- heap->in_setspecific_ = false;
- if (GetThreadHeap() == heap) {
- // Somehow heap got reinstated by a recursive call to malloc
- // from pthread_setspecific. We give up in this case.
- return;
- }
-
- // We can now get rid of the heap
- DeleteCache(heap);
-}
-
-void ThreadCache::BecomeTemporarilyIdle() {
- ThreadCache* heap = GetCacheIfPresent();
- if (heap) {
- heap->Cleanup();
-
- // Re-initialize the free list state to reset the slow-start
- // algorithm for max_size_; this avoids requesting more and more
- // memory from the central freelist due to frequent calls.
- for (size_t cl = 0; cl < kNumClasses; ++cl) {
- heap->list_[cl].Init();
- }
-
- // Re-calculate the Thread Cache max size if we have a non-default size.
- if (heap->max_size_ != kMinThreadCacheSize) {
- SpinLockHolder h(Static::pageheap_lock());
-
- // Return claimed thread space
- unclaimed_cache_space_ += heap->max_size_;
-
- // Re-init max_size_
- heap->max_size_ = 0;
- heap->IncreaseCacheLimitLocked();
-
- if (heap->max_size_ == 0) {
- // There isn't enough memory to go around. Just give the minimum to
- // this thread.
- heap->max_size_ = kMinThreadCacheSize;
-
- // Take unclaimed_cache_space_ negative.
- unclaimed_cache_space_ -= kMinThreadCacheSize;
- }
- }
- }
-}
-
-void ThreadCache::DestroyThreadCache(void* ptr) {
- // Note that "ptr" cannot be NULL since pthread promises not
- // to invoke the destructor on NULL values, but for safety,
- // we check anyway.
- if (ptr == NULL) return;
-#ifdef HAVE_TLS
- // Prevent fast path of GetThreadHeap() from returning heap.
- threadlocal_data_.heap = NULL;
- SetMinSizeForSlowPath(0);
-#endif
- DeleteCache(reinterpret_cast<ThreadCache*>(ptr));
-}
-
-void ThreadCache::DeleteCache(ThreadCache* heap) {
- // Remove all memory from heap
- heap->Cleanup();
-
- // Remove from linked list
- SpinLockHolder h(Static::pageheap_lock());
- if (heap->next_ != NULL) heap->next_->prev_ = heap->prev_;
- if (heap->prev_ != NULL) heap->prev_->next_ = heap->next_;
- if (thread_heaps_ == heap) thread_heaps_ = heap->next_;
- thread_heap_count_--;
-
- if (next_memory_steal_ == heap) next_memory_steal_ = heap->next_;
- if (next_memory_steal_ == NULL) next_memory_steal_ = thread_heaps_;
- unclaimed_cache_space_ += heap->max_size_;
-
- threadcache_allocator.Delete(heap);
-}
-
-void ThreadCache::RecomputePerThreadCacheSize() {
- // Divide available space across threads
- int n = thread_heap_count_ > 0 ? thread_heap_count_ : 1;
- size_t space = overall_thread_cache_size_ / n;
-
- // Limit to allowed range
- if (space < kMinThreadCacheSize) space = kMinThreadCacheSize;
- if (space > kMaxThreadCacheSize) space = kMaxThreadCacheSize;
-
- double ratio = space / max<double>(1, per_thread_cache_size_);
- size_t claimed = 0;
- for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) {
- // Increasing the total cache size should not circumvent the
- // slow-start growth of max_size_.
- if (ratio < 1.0) {
- h->max_size_ = static_cast<size_t>(h->max_size_ * ratio);
- }
- claimed += h->max_size_;
- }
- unclaimed_cache_space_ = overall_thread_cache_size_ - claimed;
- per_thread_cache_size_ = space;
-}
-
-void ThreadCache::GetThreadStats(uint64_t* total_bytes, uint64_t* class_count) {
- for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) {
- *total_bytes += h->Size();
- if (class_count) {
- for (int cl = 0; cl < kNumClasses; ++cl) {
- class_count[cl] += h->freelist_length(cl);
- }
- }
- }
-}
-
-void ThreadCache::set_overall_thread_cache_size(size_t new_size) {
- // Clip the value to a reasonable range
- if (new_size < kMinThreadCacheSize) new_size = kMinThreadCacheSize;
- if (new_size > (1<<30)) new_size = (1<<30); // Limit to 1GB
- overall_thread_cache_size_ = new_size;
-
- RecomputePerThreadCacheSize();
-}
-
-} // namespace tcmalloc
diff --git a/src/third_party/gperftools-2.5/src/thread_cache.h b/src/third_party/gperftools-2.5/src/thread_cache.h
deleted file mode 100644
index 445a0b57edd..00000000000
--- a/src/third_party/gperftools-2.5/src/thread_cache.h
+++ /dev/null
@@ -1,480 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Sanjay Ghemawat <opensource@google.com>
-
-#ifndef TCMALLOC_THREAD_CACHE_H_
-#define TCMALLOC_THREAD_CACHE_H_
-
-#include <config.h>
-#ifdef HAVE_PTHREAD
-#include <pthread.h> // for pthread_t, pthread_key_t
-#endif
-#include <stddef.h> // for size_t, NULL
-#ifdef HAVE_STDINT_H
-#include <stdint.h> // for uint32_t, uint64_t
-#endif
-#include <sys/types.h> // for ssize_t
-#include "base/commandlineflags.h"
-#include "common.h"
-#include "linked_list.h"
-#include "maybe_threads.h"
-#include "page_heap_allocator.h"
-#include "sampler.h"
-#include "static_vars.h"
-
-#include "common.h" // for SizeMap, kMaxSize, etc
-#include "internal_logging.h" // for ASSERT, etc
-#include "linked_list.h" // for SLL_Pop, SLL_PopRange, etc
-#include "page_heap_allocator.h" // for PageHeapAllocator
-#include "sampler.h" // for Sampler
-#include "static_vars.h" // for Static
-
-DECLARE_int64(tcmalloc_sample_parameter);
-
-namespace tcmalloc {
-
-//-------------------------------------------------------------------
-// Data kept per thread
-//-------------------------------------------------------------------
-
-class ThreadCache {
- public:
-#ifdef HAVE_TLS
- enum { have_tls = true };
-#else
- enum { have_tls = false };
-#endif
-
- // All ThreadCache objects are kept in a linked list (for stats collection)
- ThreadCache* next_;
- ThreadCache* prev_;
-
- void Init(pthread_t tid);
- void Cleanup();
-
- // Accessors (mostly just for printing stats)
- int freelist_length(size_t cl) const { return list_[cl].length(); }
-
- // Total byte size in cache
- size_t Size() const { return size_; }
-
- // Allocate an object of the given size and class. The size given
- // must be the same as the size of the class in the size map.
- void* Allocate(size_t size, size_t cl);
- void Deallocate(void* ptr, size_t size_class);
-
- void Scavenge();
-
- int GetSamplePeriod();
-
- // Record allocation of "k" bytes. Return true iff allocation
- // should be sampled
- bool SampleAllocation(size_t k);
-
- static void InitModule();
- static void InitTSD();
- static ThreadCache* GetThreadHeap();
- static ThreadCache* GetCache();
- static ThreadCache* GetCacheIfPresent();
- static ThreadCache* GetCacheWhichMustBePresent();
- static ThreadCache* CreateCacheIfNecessary();
- static void BecomeIdle();
- static void BecomeTemporarilyIdle();
- static size_t MinSizeForSlowPath();
- static void SetMinSizeForSlowPath(size_t size);
- static void SetUseEmergencyMalloc();
- static void ResetUseEmergencyMalloc();
- static bool IsUseEmergencyMalloc();
-
- static bool IsFastPathAllowed() { return MinSizeForSlowPath() != 0; }
-
- // Return the number of thread heaps in use.
- static inline int HeapsInUse();
-
- // Adds to *total_bytes the total number of bytes used by all thread heaps.
- // Also, if class_count is not NULL, it must be an array of size kNumClasses,
- // and this function will increment each element of class_count by the number
- // of items in all thread-local freelists of the corresponding size class.
- // REQUIRES: Static::pageheap_lock is held.
- static void GetThreadStats(uint64_t* total_bytes, uint64_t* class_count);
-
- // Sets the total thread cache size to new_size, recomputing the
- // individual thread cache sizes as necessary.
- // REQUIRES: Static::pageheap lock is held.
- static void set_overall_thread_cache_size(size_t new_size);
- static size_t overall_thread_cache_size() {
- return overall_thread_cache_size_;
- }
-
- private:
- class FreeList {
- private:
- void* list_; // Linked list of nodes
-
-#ifdef _LP64
- // On 64-bit hardware, manipulating 16-bit values may be slightly slow.
- uint32_t length_; // Current length.
- uint32_t lowater_; // Low water mark for list length.
- uint32_t max_length_; // Dynamic max list length based on usage.
- // Tracks the number of times a deallocation has caused
- // length_ > max_length_. After the kMaxOverages'th time, max_length_
- // shrinks and length_overages_ is reset to zero.
- uint32_t length_overages_;
-#else
- // If we aren't using 64-bit pointers then pack these into less space.
- uint16_t length_;
- uint16_t lowater_;
- uint16_t max_length_;
- uint16_t length_overages_;
-#endif
-
- public:
- void Init() {
- list_ = NULL;
- length_ = 0;
- lowater_ = 0;
- max_length_ = 1;
- length_overages_ = 0;
- }
-
- // Return current length of list
- size_t length() const {
- return length_;
- }
-
- // Return the maximum length of the list.
- size_t max_length() const {
- return max_length_;
- }
-
- // Set the maximum length of the list. If 'new_max' > length(), the
- // client is responsible for removing objects from the list.
- void set_max_length(size_t new_max) {
- max_length_ = new_max;
- }
-
- // Return the number of times that length() has gone over max_length().
- size_t length_overages() const {
- return length_overages_;
- }
-
- void set_length_overages(size_t new_count) {
- length_overages_ = new_count;
- }
-
- // Is list empty?
- bool empty() const {
- return list_ == NULL;
- }
-
- // Low-water mark management
- int lowwatermark() const { return lowater_; }
- void clear_lowwatermark() { lowater_ = length_; }
-
- void Push(void* ptr) {
- SLL_Push(&list_, ptr);
- length_++;
- }
-
- void* Pop() {
- ASSERT(list_ != NULL);
- length_--;
- if (length_ < lowater_) lowater_ = length_;
- return SLL_Pop(&list_);
- }
-
- void* Next() {
- return SLL_Next(&list_);
- }
-
- void PushRange(int N, void *start, void *end) {
- SLL_PushRange(&list_, start, end);
- length_ += N;
- }
-
- void PopRange(int N, void **start, void **end) {
- SLL_PopRange(&list_, N, start, end);
- ASSERT(length_ >= N);
- length_ -= N;
- if (length_ < lowater_) lowater_ = length_;
- }
- };
-
- // Gets and returns an object from the central cache, and, if possible,
- // also adds some objects of that size class to this thread cache.
- void* FetchFromCentralCache(size_t cl, size_t byte_size);
-
- // Releases some number of items from src. Adjusts the list's max_length
- // to eventually converge on num_objects_to_move(cl).
- void ListTooLong(FreeList* src, size_t cl);
-
- // Releases N items from this thread cache.
- void ReleaseToCentralCache(FreeList* src, size_t cl, int N);
-
- // Increase max_size_ by reducing unclaimed_cache_space_ or by
- // reducing the max_size_ of some other thread. In both cases,
- // the delta is kStealAmount.
- void IncreaseCacheLimit();
- // Same as above but requires Static::pageheap_lock() is held.
- void IncreaseCacheLimitLocked();
-
- // If TLS is available, we also store a copy of the per-thread object
- // in a __thread variable since __thread variables are faster to read
- // than pthread_getspecific(). We still need pthread_setspecific()
- // because __thread variables provide no way to run cleanup code when
- // a thread is destroyed.
- // We also give a hint to the compiler to use the "initial exec" TLS
- // model. This is faster than the default TLS model, at the cost that
- // you cannot dlopen this library. (To see the difference, look at
- // the CPU use of __tls_get_addr with and without this attribute.)
- // Since we don't really use dlopen in google code -- and using dlopen
- // on a malloc replacement is asking for trouble in any case -- that's
- // a good tradeoff for us.
-#ifdef HAVE___ATTRIBUTE__
-#define ATTR_INITIAL_EXEC __attribute__ ((tls_model ("initial-exec")))
-#else
-#define ATTR_INITIAL_EXEC
-#endif
-
-#ifdef HAVE_TLS
- struct ThreadLocalData {
- ThreadCache* heap;
- // min_size_for_slow_path is 0 if heap is NULL or kMaxSize + 1 otherwise.
- // The latter is the common case and allows allocation to be faster
- // than it would be otherwise: typically a single branch will
- // determine that the requested allocation is no more than kMaxSize
- // and we can then proceed, knowing that global and thread-local tcmalloc
- // state is initialized.
- size_t min_size_for_slow_path;
-
- bool use_emergency_malloc;
- size_t old_min_size_for_slow_path;
- };
- static __thread ThreadLocalData threadlocal_data_ ATTR_INITIAL_EXEC;
-#endif
-
- // Thread-specific key. Initialization here is somewhat tricky
- // because some Linux startup code invokes malloc() before it
- // is in a good enough state to handle pthread_keycreate().
- // Therefore, we use TSD keys only after tsd_inited is set to true.
- // Until then, we use a slow path to get the heap object.
- static bool tsd_inited_;
- static pthread_key_t heap_key_;
-
- // Linked list of heap objects. Protected by Static::pageheap_lock.
- static ThreadCache* thread_heaps_;
- static int thread_heap_count_;
-
- // A pointer to one of the objects in thread_heaps_. Represents
- // the next ThreadCache from which a thread over its max_size_ should
- // steal memory limit. Round-robin through all of the objects in
- // thread_heaps_. Protected by Static::pageheap_lock.
- static ThreadCache* next_memory_steal_;
-
- // Overall thread cache size. Protected by Static::pageheap_lock.
- static size_t overall_thread_cache_size_;
-
- // Global per-thread cache size. Writes are protected by
- // Static::pageheap_lock. Reads are done without any locking, which should be
- // fine as long as size_t can be written atomically and we don't place
- // invariants between this variable and other pieces of state.
- static volatile size_t per_thread_cache_size_;
-
- // Represents overall_thread_cache_size_ minus the sum of max_size_
- // across all ThreadCaches. Protected by Static::pageheap_lock.
- static ssize_t unclaimed_cache_space_;
-
- // This class is laid out with the most frequently used fields
- // first so that hot elements are placed on the same cache line.
-
- size_t size_; // Combined size of data
- size_t max_size_; // size_ > max_size_ --> Scavenge()
-
- // We sample allocations, biased by the size of the allocation
- Sampler sampler_; // A sampler
-
- FreeList list_[kNumClasses]; // Array indexed by size-class
-
- pthread_t tid_; // Which thread owns it
- bool in_setspecific_; // In call to pthread_setspecific?
-
- // Allocate a new heap. REQUIRES: Static::pageheap_lock is held.
- static ThreadCache* NewHeap(pthread_t tid);
-
- // Use only as pthread thread-specific destructor function.
- static void DestroyThreadCache(void* ptr);
-
- static void DeleteCache(ThreadCache* heap);
- static void RecomputePerThreadCacheSize();
-
- // Ensure that this class is cacheline-aligned. This is critical for
- // performance, as false sharing would negate many of the benefits
- // of a per-thread cache.
-} CACHELINE_ALIGNED;
-
-// Allocator for thread heaps
-// This is logically part of the ThreadCache class, but MSVC, at
-// least, does not like using ThreadCache as a template argument
-// before the class is fully defined. So we put it outside the class.
-extern PageHeapAllocator<ThreadCache> threadcache_allocator;
-
-inline int ThreadCache::HeapsInUse() {
- return threadcache_allocator.inuse();
-}
-
-inline bool ThreadCache::SampleAllocation(size_t k) {
-#ifndef NO_TCMALLOC_SAMPLES
- return UNLIKELY(FLAGS_tcmalloc_sample_parameter > 0) && sampler_.SampleAllocation(k);
-#else
- return false;
-#endif
-}
-
-inline void* ThreadCache::Allocate(size_t size, size_t cl) {
- ASSERT(size <= kMaxSize);
- ASSERT(size == Static::sizemap()->ByteSizeForClass(cl));
-
- FreeList* list = &list_[cl];
- if (UNLIKELY(list->empty())) {
- return FetchFromCentralCache(cl, size);
- }
- size_ -= size;
- return list->Pop();
-}
-
-inline void ThreadCache::Deallocate(void* ptr, size_t cl) {
- FreeList* list = &list_[cl];
- size_ += Static::sizemap()->ByteSizeForClass(cl);
- ssize_t size_headroom = max_size_ - size_ - 1;
-
- // This catches back-to-back frees of allocs in the same size
- // class. A more comprehensive (and expensive) test would be to walk
- // the entire freelist. But this might be enough to find some bugs.
- ASSERT(ptr != list->Next());
-
- list->Push(ptr);
- ssize_t list_headroom =
- static_cast<ssize_t>(list->max_length()) - list->length();
-
- // There are two relatively uncommon things that require further work.
- // In the common case we're done, and in that case we need a single branch
- // because of the bitwise-or trick that follows.
- if (UNLIKELY((list_headroom | size_headroom) < 0)) {
- if (list_headroom < 0) {
- ListTooLong(list, cl);
- }
- if (size_ >= max_size_) Scavenge();
- }
-}
-
-inline ThreadCache* ThreadCache::GetThreadHeap() {
-#ifdef HAVE_TLS
- return threadlocal_data_.heap;
-#else
- return reinterpret_cast<ThreadCache *>(
- perftools_pthread_getspecific(heap_key_));
-#endif
-}
-
-inline ThreadCache* ThreadCache::GetCacheWhichMustBePresent() {
-#ifdef HAVE_TLS
- ASSERT(threadlocal_data_.heap);
- return threadlocal_data_.heap;
-#else
- ASSERT(perftools_pthread_getspecific(heap_key_));
- return reinterpret_cast<ThreadCache *>(
- perftools_pthread_getspecific(heap_key_));
-#endif
-}
-
-inline ThreadCache* ThreadCache::GetCache() {
- ThreadCache* ptr = NULL;
- if (!tsd_inited_) {
- InitModule();
- } else {
- ptr = GetThreadHeap();
- }
- if (ptr == NULL) ptr = CreateCacheIfNecessary();
- return ptr;
-}
-
-// In deletion paths, we do not try to create a thread-cache. This is
-// because we may be in the thread destruction code and may have
-// already cleaned up the cache for this thread.
-inline ThreadCache* ThreadCache::GetCacheIfPresent() {
-#ifndef HAVE_TLS
- if (!tsd_inited_) return NULL;
-#endif
- return GetThreadHeap();
-}
-
-inline size_t ThreadCache::MinSizeForSlowPath() {
-#ifdef HAVE_TLS
- return threadlocal_data_.min_size_for_slow_path;
-#else
- return 0;
-#endif
-}
-
-inline void ThreadCache::SetMinSizeForSlowPath(size_t size) {
-#ifdef HAVE_TLS
- threadlocal_data_.min_size_for_slow_path = size;
-#endif
-}
-
-inline void ThreadCache::SetUseEmergencyMalloc() {
-#ifdef HAVE_TLS
- threadlocal_data_.old_min_size_for_slow_path = threadlocal_data_.min_size_for_slow_path;
- threadlocal_data_.min_size_for_slow_path = 0;
- threadlocal_data_.use_emergency_malloc = true;
-#endif
-}
-
-inline void ThreadCache::ResetUseEmergencyMalloc() {
-#ifdef HAVE_TLS
- threadlocal_data_.min_size_for_slow_path = threadlocal_data_.old_min_size_for_slow_path;
- threadlocal_data_.use_emergency_malloc = false;
-#endif
-}
-
-inline bool ThreadCache::IsUseEmergencyMalloc() {
-#if defined(HAVE_TLS) && defined(ENABLE_EMERGENCY_MALLOC)
- return UNLIKELY(threadlocal_data_.use_emergency_malloc);
-#else
- return false;
-#endif
-}
-
-
-} // namespace tcmalloc
-
-#endif // TCMALLOC_THREAD_CACHE_H_
diff --git a/src/third_party/gperftools-2.5/src/windows/TODO b/src/third_party/gperftools-2.5/src/windows/TODO
deleted file mode 100644
index 708ec237ac4..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/TODO
+++ /dev/null
@@ -1,86 +0,0 @@
-* Get heap-profile-table.cc using DeleteMatchingFiles
-* Get heap-profile-table.cc using FillProcSelfMaps, DumpProcSelfMaps
-* Play around with ExperimentalGetStackTrace
-* Support the windows-level memory-allocation functions? See
- /home/build/googleclient/earth/client/tools/memorytracking/client/memorytrace/src/memorytrace.cpp
- /home/build/googleclient/total_recall/common/sitestep/*
- http://www.internals.com/articles/apispy/apispy.htm
- http://www.wheaty.net/APISPY32.zip
-* Verify /proc/xxx/maps:
- http://www.geocities.com/wah_java_dotnet/procmap/index.html
-* Figure out how to edit the executable IAT so tcmalloc.dll is loaded first
-* Use QueryPerformanceCounter instead of GetTickCount() (also for sparsehash)
-
-----
-More info on windows-level memory-allocation functions:
- C runtime malloc
- LocalAlloc
- GlobalAlloc
- HeapAlloc
- VirtualAlloc
- mmap stuff
-
-malloc, LocalAlloc and GlobalAlloc call HeapAlloc, which calls
-VirtualAlloc when needed, which calls VirtualAllocEx (the __sbrk equiv?)
-
-siggi sez: If you want to do a generic job, you probably need to
-preserve the semantics of all of these Win32 calls:
- Heap32First
- Heap32ListFirst
- Heap32ListNext
- Heap32Next
- HeapAlloc
- HeapCompact
- HeapCreate
- HeapCreateTagsW
- HeapDestroy
- HeapExtend
- HeapFree
- HeapLock
- HeapQueryInformation
- HeapQueryTagW
- HeapReAlloc
- HeapSetInformation
- HeapSize
- HeapSummary
- HeapUnlock
- HeapUsage
- HeapValidate
- HeapWalk
-
-kernel32.dll export functions and nt.dll export functions:
- http://www.shorthike.com/svn/trunk/tools_win32/dm/lib/kernel32.def
- http://undocumented.ntinternals.net/
-
-You can edit the executable IAT to have the patching DLL be the
-first one loaded.
-
-Most complete way to intercept system calls is patch the functions
-(not the IAT).
-
-Microsoft has somee built-in routines for heap-checking:
- http://support.microsoft.com/kb/268343
-
-----
-Itimer replacement:
- http://msdn2.microsoft.com/en-us/library/ms712713.aspx
-
-----
-Changes I've had to make to the project file:
-
-0) When creating the project file, click on "no autogenerated files"
-
---- For each project:
-1) Alt-F7 -> General -> [pulldown "all configurations" ] -> Output Directory -> $(SolutionDir)$(ConfigurationName)
-2) Alt-F7 -> General -> [pulldown "all configurations" ] -> Intermediate Directory -> $(ConfigurationName)
-
---- For each .cc file:
-1) Alt-F7 -> C/C++ -> General -> [pulldown "all configurations"] -> Additional Include Directives --> src/windows + src/
-2) Alt-F7 -> C/C++ -> Code Generation -> Runtime Library -> Multi-threaded, debug/release, DLL or not
-
---- For DLL:
-3) Alt-F7 -> Linker -> Input -> [pulldown "all configurations" ] -> Module Definition File -> src\windows\vc7and8.def
---- For binaries depending on a DLL:
-3) Right-click on project -> Project Dependencies -> [add dll]
---- For static binaries (not depending on a DLL)
-3) Alt-F7 -> C/C++ -> Command Line -> [pulldown "all configurations"] -> /D PERFTOOLS_DLL_DECL=
diff --git a/src/third_party/gperftools-2.5/src/windows/addr2line-pdb.c b/src/third_party/gperftools-2.5/src/windows/addr2line-pdb.c
deleted file mode 100644
index 5c65a0357e5..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/addr2line-pdb.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/* 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: David Vitek
- *
- * Dump function addresses using Microsoft debug symbols. This works
- * on PDB files. Note that this program will download symbols to
- * c:\websymbols without asking.
- */
-
-#define WIN32_LEAN_AND_MEAN
-#define _CRT_SECURE_NO_WARNINGS
-#define _CRT_SECURE_NO_DEPRECATE
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <windows.h>
-#include <dbghelp.h>
-
-#define SEARCH_CAP (1024*1024)
-#define WEBSYM "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols"
-
-void usage() {
- fprintf(stderr, "usage: "
- "addr2line-pdb [-f|--functions] [-C|--demangle] [-e filename]\n");
- fprintf(stderr, "(Then list the hex addresses on stdin, one per line)\n");
-}
-
-int main(int argc, char *argv[]) {
- DWORD error;
- HANDLE process;
- ULONG64 module_base;
- int i;
- char* search;
- char buf[256]; /* Enough to hold one hex address, I trust! */
- int rv = 0;
- /* We may add SYMOPT_UNDNAME if --demangle is specified: */
- DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES;
- char* filename = "a.out"; /* The default if -e isn't specified */
- int print_function_name = 0; /* Set to 1 if -f is specified */
-
- for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "--functions") == 0 || strcmp(argv[i], "-f") == 0) {
- print_function_name = 1;
- } else if (strcmp(argv[i], "--demangle") == 0 ||
- strcmp(argv[i], "-C") == 0) {
- symopts |= SYMOPT_UNDNAME;
- } else if (strcmp(argv[i], "-e") == 0) {
- if (i + 1 >= argc) {
- fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n");
- return 1;
- }
- filename = argv[i+1];
- i++; /* to skip over filename too */
- } else if (strcmp(argv[i], "--help") == 0) {
- usage();
- exit(0);
- } else {
- usage();
- exit(1);
- }
- }
-
- process = GetCurrentProcess();
-
- if (!SymInitialize(process, NULL, FALSE)) {
- error = GetLastError();
- fprintf(stderr, "SymInitialize returned error : %d\n", error);
- return 1;
- }
-
- search = malloc(SEARCH_CAP);
- if (SymGetSearchPath(process, search, SEARCH_CAP)) {
- if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) {
- fprintf(stderr, "Search path too long\n");
- SymCleanup(process);
- return 1;
- }
- strcat(search, ";" WEBSYM);
- } else {
- error = GetLastError();
- fprintf(stderr, "SymGetSearchPath returned error : %d\n", error);
- rv = 1; /* An error, but not a fatal one */
- strcpy(search, WEBSYM); /* Use a default value */
- }
- if (!SymSetSearchPath(process, search)) {
- error = GetLastError();
- fprintf(stderr, "SymSetSearchPath returned error : %d\n", error);
- rv = 1; /* An error, but not a fatal one */
- }
-
- SymSetOptions(symopts);
- module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0);
- if (!module_base) {
- /* SymLoadModuleEx failed */
- error = GetLastError();
- fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n",
- error, filename);
- SymCleanup(process);
- return 1;
- }
-
- buf[sizeof(buf)-1] = '\0'; /* Just to be safe */
- while (fgets(buf, sizeof(buf)-1, stdin)) {
- /* GNU addr2line seems to just do a strtol and ignore any
- * weird characters it gets, so we will too.
- */
- unsigned __int64 addr = _strtoui64(buf, NULL, 16);
- ULONG64 buffer[(sizeof(SYMBOL_INFO) +
- MAX_SYM_NAME*sizeof(TCHAR) +
- sizeof(ULONG64) - 1)
- / sizeof(ULONG64)];
- PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
- IMAGEHLP_LINE64 line;
- DWORD dummy;
- pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
- pSymbol->MaxNameLen = MAX_SYM_NAME;
- if (print_function_name) {
- if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) {
- printf("%s\n", pSymbol->Name);
- } else {
- printf("??\n");
- }
- }
- line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
- if (SymGetLineFromAddr64(process, (DWORD64)addr, &dummy, &line)) {
- printf("%s:%d\n", line.FileName, (int)line.LineNumber);
- } else {
- printf("??:0\n");
- }
- }
- SymUnloadModule64(process, module_base);
- SymCleanup(process);
- return rv;
-}
diff --git a/src/third_party/gperftools-2.5/src/windows/auto_testing_hook.h b/src/third_party/gperftools-2.5/src/windows/auto_testing_hook.h
deleted file mode 100644
index fc2b71013e9..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/auto_testing_hook.h
+++ /dev/null
@@ -1,156 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2010 The Chromium Authors. 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.
-//
-// Utility for using SideStep with unit tests.
-
-#ifndef CEEE_TESTING_SIDESTEP_AUTO_TESTING_HOOK_H_
-#define CEEE_TESTING_SIDESTEP_AUTO_TESTING_HOOK_H_
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "preamble_patcher.h"
-
-#define SIDESTEP_CHK(x) CHECK(x)
-#define SIDESTEP_EXPECT_TRUE(x) SIDESTEP_CHK(x)
-
-namespace sidestep {
-
-// Same trick as common/scope_cleanup.h ScopeGuardImplBase
-class AutoTestingHookBase {
- public:
- virtual ~AutoTestingHookBase() {}
-};
-
-// This is the typedef you normally use for the class, e.g.
-//
-// AutoTestingHook hook = MakeTestingHook(TargetFunc, HookTargetFunc);
-//
-// The 'hook' variable will then be destroyed when it goes out of scope.
-//
-// NOTE: You must not hold this type as a member of another class. Its
-// destructor will not get called.
-typedef const AutoTestingHookBase& AutoTestingHook;
-
-// This is the class you must use when holding a hook as a member of another
-// class, e.g.
-//
-// public:
-// AutoTestingHookHolder holder_;
-// MyClass() : my_hook_holder(MakeTestingHookHolder(Target, Hook)) {}
-class AutoTestingHookHolder {
- public:
- explicit AutoTestingHookHolder(AutoTestingHookBase* hook) : hook_(hook) {}
- ~AutoTestingHookHolder() { delete hook_; }
- private:
- AutoTestingHookHolder() {} // disallow
- AutoTestingHookBase* hook_;
-};
-
-// This class helps patch a function, then unpatch it when the object exits
-// scope, and also maintains the pointer to the original function stub.
-//
-// To enable use of the class without having to explicitly provide the
-// type of the function pointers (and instead only providing it
-// implicitly) we use the same trick as ScopeGuard (see
-// common/scope_cleanup.h) uses, so to create a hook you use the MakeHook
-// function rather than a constructor.
-//
-// NOTE: This function is only safe for e.g. unit tests and _not_ for
-// production code. See PreamblePatcher class for details.
-template <typename T>
-class AutoTestingHookImpl : public AutoTestingHookBase {
- public:
- static AutoTestingHookImpl<T> MakeTestingHook(T target_function,
- T replacement_function,
- bool do_it) {
- return AutoTestingHookImpl<T>(target_function, replacement_function, do_it);
- }
-
- static AutoTestingHookImpl<T>* MakeTestingHookHolder(T target_function,
- T replacement_function,
- bool do_it) {
- return new AutoTestingHookImpl<T>(target_function,
- replacement_function, do_it);
- }
-
- ~AutoTestingHookImpl() {
- if (did_it_) {
- SIDESTEP_CHK(SIDESTEP_SUCCESS == PreamblePatcher::Unpatch(
- (void*)target_function_, (void*)replacement_function_,
- (void*)original_function_));
- }
- }
-
- // Returns a pointer to the original function. To use this method you will
- // have to explicitly create an AutoTestingHookImpl of the specific
- // function pointer type (i.e. not use the AutoTestingHook typedef).
- T original_function() {
- return original_function_;
- }
-
- private:
- AutoTestingHookImpl(T target_function, T replacement_function, bool do_it)
- : target_function_(target_function),
- original_function_(NULL),
- replacement_function_(replacement_function),
- did_it_(do_it) {
- if (do_it) {
- SIDESTEP_CHK(SIDESTEP_SUCCESS == PreamblePatcher::Patch(target_function,
- replacement_function,
- &original_function_));
- }
- }
-
- T target_function_; // always valid
- T original_function_; // always valid
- T replacement_function_; // always valid
- bool did_it_; // Remember if we did it or not...
-};
-
-template <typename T>
-inline AutoTestingHookImpl<T> MakeTestingHook(T target,
- T replacement,
- bool do_it) {
- return AutoTestingHookImpl<T>::MakeTestingHook(target, replacement, do_it);
-}
-
-template <typename T>
-inline AutoTestingHookImpl<T> MakeTestingHook(T target, T replacement) {
- return AutoTestingHookImpl<T>::MakeTestingHook(target, replacement, true);
-}
-
-template <typename T>
-inline AutoTestingHookImpl<T>* MakeTestingHookHolder(T target, T replacement) {
- return AutoTestingHookImpl<T>::MakeTestingHookHolder(target, replacement,
- true);
-}
-
-}; // namespace sidestep
-
-#endif // CEEE_TESTING_SIDESTEP_AUTO_TESTING_HOOK_H_
diff --git a/src/third_party/gperftools-2.5/src/windows/config.h b/src/third_party/gperftools-2.5/src/windows/config.h
deleted file mode 100644
index 6bbeb1afb1a..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/config.h
+++ /dev/null
@@ -1,320 +0,0 @@
-/* A manual version of config.h fit for windows machines.
- *
- * Use of this source code is governed by a BSD-style license that can
- * be found in the LICENSE file.
- */
-
-/* Sometimes we accidentally #include this config.h instead of the one
- in .. -- this is particularly true for msys/mingw, which uses the
- unix config.h but also runs code in the windows directory.
- */
-#ifdef __MINGW32__
-#include "../config.h"
-#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_
-#endif
-
-#ifndef GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_
-#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_
-/* used by tcmalloc.h */
-#define GPERFTOOLS_CONFIG_H_
-
-/* define this if you are linking tcmalloc statically and overriding the
- * default allocators.
- * For instructions on how to use this mode, see
- * http://groups.google.com/group/google-perftools/browse_thread/thread/41cd3710af85e57b
- */
-#undef WIN32_OVERRIDE_ALLOCATORS
-
-/* Define to 1 if your libc has a snprintf implementation */
-#if defined(_MSC_VER) && _MSC_VER >= 1900
-#define HAVE_SNPRINTF 1
-#else
-#undef HAVE_SNPRINTF
-#endif
-
-/* Define to 1 if compiler supports __builtin_stack_pointer */
-#undef HAVE_BUILTIN_STACK_POINTER
-
-/* Define to 1 if you have the <conflict-signal.h> header file. */
-#undef HAVE_CONFLICT_SIGNAL_H
-
-/* Define to 1 if you have the <cygwin/signal.h> header file. */
-#undef HAVE_CYGWIN_SIGNAL_H
-
-/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
- */
-#undef HAVE_DECL_CFREE
-
-/* Define to 1 if you have the declaration of `memalign', and to 0 if you
- don't. */
-#undef HAVE_DECL_MEMALIGN
-
-/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
- you don't. */
-#undef HAVE_DECL_POSIX_MEMALIGN
-
-/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
- don't. */
-#undef HAVE_DECL_PVALLOC
-
-/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
- */
-#undef HAVE_DECL_UNAME
-
-/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
- */
-#undef HAVE_DECL_VALLOC
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if the system has the type `Elf32_Versym'. */
-#undef HAVE_ELF32_VERSYM
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#undef HAVE_EXECINFO_H
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
-/* Define to 1 if you have the <features.h> header file. */
-#undef HAVE_FEATURES_H
-
-/* Define to 1 if you have the `geteuid' function. */
-#undef HAVE_GETEUID
-
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1 /* we define it in windows/port.cc */
-
-/* Define to 1 if you have the <glob.h> header file. */
-#undef HAVE_GLOB_H
-
-/* Define to 1 if you have the <grp.h> header file. */
-#undef HAVE_GRP_H
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-#undef HAVE_LIBUNWIND_H
-
-/* Define to 1 if you have the <linux/ptrace.h> header file. */
-#undef HAVE_LINUX_PTRACE_H
-
-/* 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
-
-/* Define to 1 if you have a working `mmap' system call. */
-#undef HAVE_MMAP
-
-/* define if the compiler implements namespaces */
-#define HAVE_NAMESPACES 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#undef HAVE_POLL_H
-
-/* define if libc has program_invocation_name */
-#undef HAVE_PROGRAM_INVOCATION_NAME
-
-/* Define if you have POSIX threads libraries and header files. */
-#undef HAVE_PTHREAD
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#undef HAVE_PWD_H
-
-/* Define to 1 if you have the `sbrk' function. */
-#undef HAVE_SBRK
-
-/* Define to 1 if you have the <sched.h> header file. */
-#undef HAVE_SCHED_H
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#if defined(_MSC_VER) && _MSC_VER >= 1900
-#define HAVE_STDINT_H 1
-#else
-#undef HAVE_STDINT_H
-#endif
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* 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
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#undef HAVE_SYS_PRCTL_H
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#undef HAVE_SYS_RESOURCE_H
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#undef HAVE_SYS_SOCKET_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#undef HAVE_SYS_SYSCALL_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* <sys/ucontext.h> is broken on redhat 7 */
-#undef HAVE_SYS_UCONTEXT_H
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#undef HAVE_SYS_WAIT_H
-
-/* Define to 1 if compiler supports __thread */
-#define HAVE_TLS 1
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-#undef HAVE_UCONTEXT_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the <unwind.h> header file. */
-#undef HAVE_UNWIND_H
-
-/* Define to 1 if you have the <valgrind.h> header file. */
-#undef HAVE_VALGRIND_H
-
-/* define if your compiler has __attribute__ */
-#undef HAVE___ATTRIBUTE__
-
-/* Define to 1 if compiler supports __environ */
-#undef HAVE___ENVIRON
-
-/* Define to 1 if the system has the type `__int64'. */
-#define HAVE___INT64 1
-
-/* prefix where we look for installed files */
-#undef INSTALL_PREFIX
-
-/* Define to 1 if int32_t is equivalent to intptr_t */
-#undef INT32_EQUALS_INTPTR
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#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
-
-/* Name of package */
-#define PACKAGE "gperftools"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gperftools@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "gperftools"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "gperftools 2.5"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gperftools"
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.5"
-
-/* How to access the PC from a struct ucontext */
-#undef PC_FROM_UCONTEXT
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#ifndef PERFTOOLS_DLL_DECL
-# define PERFTOOLS_IS_A_DLL 1 /* not set if you're statically linking */
-# define PERFTOOLS_DLL_DECL __declspec(dllexport)
-# define PERFTOOLS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
-#endif
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIdS "Id"
-
-/* printf format code for printing a size_t and ssize_t */
-#define PRIuS "Iu"
-
-/* 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
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* the namespace where STL code like vector<> is defined */
-#define STL_NAMESPACE std
-
-/* Version number of package */
-#undef VERSION
-
-/* C99 says: define this to get the PRI... macros from stdint.h */
-#ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS 1
-#endif
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-#undef inline
-#endif
-
-// ---------------------------------------------------------------------
-// Extra stuff not found in config.h.in
-
-// This must be defined before the windows.h is included. We need at
-// least 0x0400 for mutex.h to have access to TryLock, and at least
-// 0x0501 for patch_functions.cc to have access to GetModuleHandleEx.
-// (This latter is an optimization we could take out if need be.)
-#ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0501
-#endif
-
-// We want to make sure not to ever try to #include heap-checker.h
-#define NO_HEAP_CHECK 1
-
-// TODO(csilvers): include windows/port.h in every relevant source file instead?
-#include "windows/port.h"
-
-#endif /* GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ */
diff --git a/src/third_party/gperftools-2.5/src/windows/get_mangled_names.cc b/src/third_party/gperftools-2.5/src/windows/get_mangled_names.cc
deleted file mode 100644
index 08bd03be6fb..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/get_mangled_names.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// 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: Craig Silverstein (opensource@google.com)
-
-// When you are porting perftools to a new compiler or architecture
-// (win64 vs win32) for instance, you'll need to change the mangled
-// symbol names for operator new and friends at the top of
-// patch_functions.cc. This file helps you do that.
-//
-// It does this by defining these functions with the proper signature.
-// All you need to do is compile this file and the run dumpbin on it.
-// (See http://msdn.microsoft.com/en-us/library/5x49w699.aspx for more
-// on dumpbin). To do this in MSVC, use the MSVC commandline shell:
-// http://msdn.microsoft.com/en-us/library/ms235639(VS.80).aspx)
-//
-// The run:
-// cl /c get_mangled_names.cc
-// dumpbin /symbols get_mangled_names.obj
-//
-// It will print out the mangled (and associated unmangled) names of
-// the 8 symbols you need to put at the top of patch_functions.cc
-
-#include <sys/types.h> // for size_t
-#include <new> // for nothrow_t
-
-static char m; // some dummy memory so new doesn't return NULL.
-
-void* operator new(size_t size) { return &m; }
-void operator delete(void* p) throw() { }
-void* operator new[](size_t size) { return &m; }
-void operator delete[](void* p) throw() { }
-
-void* operator new(size_t size, const std::nothrow_t&) throw() { return &m; }
-void operator delete(void* p, const std::nothrow_t&) throw() { }
-void* operator new[](size_t size, const std::nothrow_t&) throw() { return &m; }
-void operator delete[](void* p, const std::nothrow_t&) throw() { }
diff --git a/src/third_party/gperftools-2.5/src/windows/gperftools/tcmalloc.h b/src/third_party/gperftools-2.5/src/windows/gperftools/tcmalloc.h
deleted file mode 100644
index 1140a65f939..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/gperftools/tcmalloc.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2003, 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>
- * .h file by Craig Silverstein <opensource@google.com>
- */
-
-#ifndef TCMALLOC_TCMALLOC_H_
-#define TCMALLOC_TCMALLOC_H_
-
-#include <stddef.h> /* for size_t */
-
-/* Define the version number so folks can check against it */
-#define TC_VERSION_MAJOR 2
-#define TC_VERSION_MINOR 5
-#define TC_VERSION_PATCH ""
-#define TC_VERSION_STRING "gperftools 2.5"
-
-#ifdef __cplusplus
-#define PERFTOOLS_THROW throw()
-#else
-# ifdef __GNUC__
-# define PERFTOOLS_THROW __attribute__((__nothrow__))
-# else
-# define PERFTOOLS_THROW
-# endif
-#endif
-
-#ifndef PERFTOOLS_DLL_DECL
-#define PERFTOOLS_DLL_DECL_DEFINED
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-#ifdef __cplusplus
-namespace std {
-struct nothrow_t;
-}
-
-extern "C" {
-#endif
- /*
- * Returns a human-readable version string. If major, minor,
- * and/or patch are not NULL, they are set to the major version,
- * minor version, and patch-code (a string, usually "").
- */
- PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor,
- const char** patch) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
- size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
- size_t align, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_THROW;
-
- /*
- * This is an alias for MallocExtension::instance()->GetAllocatedSize().
- * It is equivalent to
- * OS X: malloc_size()
- * glibc: malloc_usable_size()
- * Windows: _msize()
- */
- PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_THROW;
-
-#ifdef __cplusplus
- PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_new(size_t size);
- PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
- PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
-}
-#endif
-
-/* We're only un-defining those for public */
-#if !defined(GPERFTOOLS_CONFIG_H_)
-
-#undef PERFTOOLS_THROW
-
-#ifdef PERFTOOLS_DLL_DECL_DEFINED
-#undef PERFTOOLS_DLL_DECL
-#undef PERFTOOLS_DLL_DECL_DEFINED
-#endif
-
-#endif /* GPERFTOOLS_CONFIG_H_ */
-
-#endif /* #ifndef TCMALLOC_TCMALLOC_H_ */
diff --git a/src/third_party/gperftools-2.5/src/windows/gperftools/tcmalloc.h.in b/src/third_party/gperftools-2.5/src/windows/gperftools/tcmalloc.h.in
deleted file mode 100644
index 66bbdb835f6..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/gperftools/tcmalloc.h.in
+++ /dev/null
@@ -1,139 +0,0 @@
-// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2003, 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>
- * .h file by Craig Silverstein <opensource@google.com>
- */
-
-#ifndef TCMALLOC_TCMALLOC_H_
-#define TCMALLOC_TCMALLOC_H_
-
-#include <stddef.h> /* for size_t */
-
-/* Define the version number so folks can check against it */
-#define TC_VERSION_MAJOR @TC_VERSION_MAJOR@
-#define TC_VERSION_MINOR @TC_VERSION_MINOR@
-#define TC_VERSION_PATCH "@TC_VERSION_PATCH@"
-#define TC_VERSION_STRING "gperftools @TC_VERSION_MAJOR@.@TC_VERSION_MINOR@@TC_VERSION_PATCH@"
-
-#ifdef __cplusplus
-#define PERFTOOLS_THROW throw()
-#else
-# ifdef __GNUC__
-# define PERFTOOLS_THROW __attribute__((__nothrow__))
-# else
-# define PERFTOOLS_THROW
-# endif
-#endif
-
-#ifndef PERFTOOLS_DLL_DECL
-#define PERFTOOLS_DLL_DECL_DEFINED
-# ifdef _WIN32
-# define PERFTOOLS_DLL_DECL __declspec(dllimport)
-# else
-# define PERFTOOLS_DLL_DECL
-# endif
-#endif
-
-#ifdef __cplusplus
-namespace std {
-struct nothrow_t;
-}
-
-extern "C" {
-#endif
- /*
- * Returns a human-readable version string. If major, minor,
- * and/or patch are not NULL, they are set to the major version,
- * minor version, and patch-code (a string, usually "").
- */
- PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor,
- const char** patch) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
- size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
- size_t align, size_t size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) PERFTOOLS_THROW;
-
- PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_THROW;
-
- /*
- * This is an alias for MallocExtension::instance()->GetAllocatedSize().
- * It is equivalent to
- * OS X: malloc_size()
- * glibc: malloc_usable_size()
- * Windows: _msize()
- */
- PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_THROW;
-
-#ifdef __cplusplus
- PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_new(size_t size);
- PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
- PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
- const std::nothrow_t&) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_THROW;
- PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) throw();
- PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
- const std::nothrow_t&) PERFTOOLS_THROW;
-}
-#endif
-
-/* We're only un-defining those for public */
-#if !defined(GPERFTOOLS_CONFIG_H_)
-
-#undef PERFTOOLS_THROW
-
-#ifdef PERFTOOLS_DLL_DECL_DEFINED
-#undef PERFTOOLS_DLL_DECL
-#undef PERFTOOLS_DLL_DECL_DEFINED
-#endif
-
-#endif /* GPERFTOOLS_CONFIG_H_ */
-
-#endif /* #ifndef TCMALLOC_TCMALLOC_H_ */
diff --git a/src/third_party/gperftools-2.5/src/windows/ia32_modrm_map.cc b/src/third_party/gperftools-2.5/src/windows/ia32_modrm_map.cc
deleted file mode 100644
index f1f1906289c..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/ia32_modrm_map.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Copyright (c) 2007, 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: Joi Sigurdsson
- *
- * Table of relevant information about how to decode the ModR/M byte.
- * Based on information in the IA-32 Intel® Architecture
- * Software Developer’s Manual Volume 2: Instruction Set Reference.
- */
-
-#include "mini_disassembler.h"
-#include "mini_disassembler_types.h"
-
-namespace sidestep {
-
-const ModrmEntry MiniDisassembler::s_ia16_modrm_map_[] = {
-// mod == 00
- /* r/m == 000 */ { false, false, OS_ZERO },
- /* r/m == 001 */ { false, false, OS_ZERO },
- /* r/m == 010 */ { false, false, OS_ZERO },
- /* r/m == 011 */ { false, false, OS_ZERO },
- /* r/m == 100 */ { false, false, OS_ZERO },
- /* r/m == 101 */ { false, false, OS_ZERO },
- /* r/m == 110 */ { true, false, OS_WORD },
- /* r/m == 111 */ { false, false, OS_ZERO },
-// mod == 01
- /* r/m == 000 */ { true, false, OS_BYTE },
- /* r/m == 001 */ { true, false, OS_BYTE },
- /* r/m == 010 */ { true, false, OS_BYTE },
- /* r/m == 011 */ { true, false, OS_BYTE },
- /* r/m == 100 */ { true, false, OS_BYTE },
- /* r/m == 101 */ { true, false, OS_BYTE },
- /* r/m == 110 */ { true, false, OS_BYTE },
- /* r/m == 111 */ { true, false, OS_BYTE },
-// mod == 10
- /* r/m == 000 */ { true, false, OS_WORD },
- /* r/m == 001 */ { true, false, OS_WORD },
- /* r/m == 010 */ { true, false, OS_WORD },
- /* r/m == 011 */ { true, false, OS_WORD },
- /* r/m == 100 */ { true, false, OS_WORD },
- /* r/m == 101 */ { true, false, OS_WORD },
- /* r/m == 110 */ { true, false, OS_WORD },
- /* r/m == 111 */ { true, false, OS_WORD },
-// mod == 11
- /* r/m == 000 */ { false, false, OS_ZERO },
- /* r/m == 001 */ { false, false, OS_ZERO },
- /* r/m == 010 */ { false, false, OS_ZERO },
- /* r/m == 011 */ { false, false, OS_ZERO },
- /* r/m == 100 */ { false, false, OS_ZERO },
- /* r/m == 101 */ { false, false, OS_ZERO },
- /* r/m == 110 */ { false, false, OS_ZERO },
- /* r/m == 111 */ { false, false, OS_ZERO }
-};
-
-const ModrmEntry MiniDisassembler::s_ia32_modrm_map_[] = {
-// mod == 00
- /* r/m == 000 */ { false, false, OS_ZERO },
- /* r/m == 001 */ { false, false, OS_ZERO },
- /* r/m == 010 */ { false, false, OS_ZERO },
- /* r/m == 011 */ { false, false, OS_ZERO },
- /* r/m == 100 */ { false, true, OS_ZERO },
- /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 110 */ { false, false, OS_ZERO },
- /* r/m == 111 */ { false, false, OS_ZERO },
-// mod == 01
- /* r/m == 000 */ { true, false, OS_BYTE },
- /* r/m == 001 */ { true, false, OS_BYTE },
- /* r/m == 010 */ { true, false, OS_BYTE },
- /* r/m == 011 */ { true, false, OS_BYTE },
- /* r/m == 100 */ { true, true, OS_BYTE },
- /* r/m == 101 */ { true, false, OS_BYTE },
- /* r/m == 110 */ { true, false, OS_BYTE },
- /* r/m == 111 */ { true, false, OS_BYTE },
-// mod == 10
- /* r/m == 000 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 001 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 010 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 011 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 100 */ { true, true, OS_DOUBLE_WORD },
- /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 110 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 111 */ { true, false, OS_DOUBLE_WORD },
-// mod == 11
- /* r/m == 000 */ { false, false, OS_ZERO },
- /* r/m == 001 */ { false, false, OS_ZERO },
- /* r/m == 010 */ { false, false, OS_ZERO },
- /* r/m == 011 */ { false, false, OS_ZERO },
- /* r/m == 100 */ { false, false, OS_ZERO },
- /* r/m == 101 */ { false, false, OS_ZERO },
- /* r/m == 110 */ { false, false, OS_ZERO },
- /* r/m == 111 */ { false, false, OS_ZERO },
-};
-
-}; // namespace sidestep
diff --git a/src/third_party/gperftools-2.5/src/windows/ia32_opcode_map.cc b/src/third_party/gperftools-2.5/src/windows/ia32_opcode_map.cc
deleted file mode 100644
index ba6a79e3d19..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/ia32_opcode_map.cc
+++ /dev/null
@@ -1,1219 +0,0 @@
-/* Copyright (c) 2007, 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: Joi Sigurdsson
- *
- * Opcode decoding maps. Based on the IA-32 Intel® Architecture
- * Software Developer’s Manual Volume 2: Instruction Set Reference. Idea
- * for how to lay out the tables in memory taken from the implementation
- * in the Bastard disassembly environment.
- */
-
-#include "mini_disassembler.h"
-
-namespace sidestep {
-
-/*
-* This is the first table to be searched; the first field of each
-* Opcode in the table is either 0 to indicate you're in the
-* right table, or an index to the correct table, in the global
-* map g_pentiumOpcodeMap
-*/
-const Opcode s_first_opcode_byte[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF */ { 1, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x10 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x11 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x12 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x13 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x14 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x15 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x16 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x17 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x18 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x19 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1E */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1F */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x20 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x21 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x22 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x23 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x24 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x25 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x26 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x27 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "daa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x28 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x29 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "das", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x30 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x31 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x32 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x33 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x34 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x35 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x36 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x37 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aaa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x38 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x39 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aas", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-#ifdef _M_X64
- /* REX Prefixes in 64-bit mode. */
- /* 0x40 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x41 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x42 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x43 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x44 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x45 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x46 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x47 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x48 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x49 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4A */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4B */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4C */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4D */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4F */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-#else
- /* 0x40 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x41 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x42 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x43 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x44 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x45 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x46 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x47 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x48 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x49 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-#endif
- /* 0x50 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x51 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x52 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x53 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x54 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x55 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x56 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x57 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x58 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x59 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x60 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x61 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x62 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_A, AM_NOT_USED, "bound", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x63 */ { 0, IT_GENERIC, AM_E | OT_W, AM_G | OT_W, AM_NOT_USED, "arpl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x64 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x65 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x66 */ { 0, IT_PREFIX_OPERAND, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x67 */ { 0, IT_PREFIX_ADDRESS, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x68 */ { 0, IT_GENERIC, AM_I | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x69 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_V, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6A */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_B, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6C */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "insb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6D */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "insd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6E */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X | OT_B, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X | OT_V, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x70 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x71 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x72 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x73 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x74 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x75 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x76 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x77 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x78 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x79 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7A */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7B */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7C */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7D */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7E */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7F */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x80 */ { 2, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x81 */ { 3, IT_REFERENCE, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x82 */ { 4, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x83 */ { 5, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x84 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x85 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x86 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x87 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x88 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x89 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8C */ { 0, IT_GENERIC, AM_E | OT_W, AM_S | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8D */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, "lea", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8E */ { 0, IT_GENERIC, AM_S | OT_W, AM_E | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8F */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x90 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "nop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x91 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x92 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x93 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x94 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x95 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x96 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x97 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x98 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cwde", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x99 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cdq", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9A */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "callf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9B */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wait", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9E */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_O | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_O | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA2 */ { 0, IT_GENERIC, AM_O | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA3 */ { 0, IT_GENERIC, AM_O | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA4 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "movsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA5 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "movsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA6 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "cmpsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA7 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "cmpsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAA */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "stosb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAB */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "stosd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X| OT_B, AM_NOT_USED, "lodsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X| OT_V, AM_NOT_USED, "lodsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAE */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_Y | OT_B, AM_NOT_USED, "scasb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_Y | OT_V, AM_NOT_USED, "scasd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB1 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB2 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB3 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-#ifdef _M_X64
- /* 0xB8 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBA */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBB */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBC */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBE */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-#else
- /* 0xB8 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBA */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBB */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBC */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBE */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-#endif
- /* 0xC0 */ { 6, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC1 */ { 7, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC2 */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC3 */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC4 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "les", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "lds", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC8 */ { 0, IT_GENERIC, AM_I | OT_W, AM_I | OT_B, AM_NOT_USED, "enter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "leave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCA */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCB */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "int3", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCD */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "int", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCE */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "into", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCF */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "iret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD0 */ { 8, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD1 */ { 9, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD2 */ { 10, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD3 */ { 11, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD4 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aam", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD5 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "xlat", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-
- // The following 8 lines would be references to the FPU tables, but we currently
- // do not support the FPU instructions in this disassembler.
-
- /* 0xD8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDA */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDB */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDC */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDD */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDE */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDF */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-
-
- /* 0xE0 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE1 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE2 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE3 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jcxz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE6 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE7 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE8 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE9 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEA */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEB */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xED */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEF */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_V, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF0 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lock:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF2 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "repne:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF3 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rep:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF4 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "hlt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF6 */ { 12, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF7 */ { 13, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cli", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFB */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFD */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "std", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFE */ { 14, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFF */ { 15, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f[] = {
- /* 0x0 */ { 16, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 17, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lsl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "invd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wbinvd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud2", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x10 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movups", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "movsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "movss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movupd" } },
- /* 0x11 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movups", true,
- /* F2h */ { 0, IT_GENERIC, AM_W | OT_SD, AM_V | OT_SD, AM_NOT_USED, "movsd" },
- /* F3h */ { 0, IT_GENERIC, AM_W | OT_SS, AM_V | OT_SS, AM_NOT_USED, "movss" },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movupd" } },
- /* 0x12 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // only one of ...
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // ...these two is correct, Intel doesn't specify which
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_S, AM_NOT_USED, "movlpd" } },
- /* 0x13 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlpd" } },
- /* 0x14 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpcklps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpcklpd" } },
- /* 0x15 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpckhps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpckhpd" } },
- /* 0x16 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // only one of...
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // ...these two is correct, Intel doesn't specify which
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhpd" } },
- /* 0x17 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhpd" } },
- /* 0x18 */ { 18, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x19 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1C */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x20 */ { 0, IT_GENERIC, AM_R | OT_D, AM_C | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x21 */ { 0, IT_GENERIC, AM_R | OT_D, AM_D | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x22 */ { 0, IT_GENERIC, AM_C | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x23 */ { 0, IT_GENERIC, AM_D | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x24 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x25 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x26 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x27 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x28 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movaps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movapd" } },
- /* 0x29 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movaps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movapd" } },
- /* 0x2A */ { 0, IT_GENERIC, AM_V | OT_PS, AM_Q | OT_Q, AM_NOT_USED, "cvtpi2ps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_E | OT_D, AM_NOT_USED, "cvtsi2sd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_E | OT_D, AM_NOT_USED, "cvtsi2ss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_Q | OT_DQ, AM_NOT_USED, "cvtpi2pd" } },
- /* 0x2B */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movntps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movntpd" } },
- /* 0x2C */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvttps2pi", true,
- /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvttsd2si" },
- /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvttss2si" },
- /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2pi" } },
- /* 0x2D */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvtps2pi", true,
- /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvtsd2si" },
- /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvtss2si" },
- /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2pi" } },
- /* 0x2E */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "ucomiss", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "ucomisd" } },
- /* 0x2F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_SS, AM_NOT_USED, "comiss", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "comisd" } },
- /* 0x30 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wrmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x31 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdtsc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x32 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x33 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdpmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x34 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysenter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x35 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysexit", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x36 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x37 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x38 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x39 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x40 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x41 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x42 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x43 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x44 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x45 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x46 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x47 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmova", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x48 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x49 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4A */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4D */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4E */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4F */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x50 */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PS, AM_NOT_USED, "movmskps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PD, AM_NOT_USED, "movmskpd" } },
- /* 0x51 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "sqrtps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "sqrtsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "sqrtss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "sqrtpd" } },
- /* 0x52 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rsqrtps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rsqrtss" },
- /* 66h */ { 0 } },
- /* 0x53 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rcpps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rcpss" },
- /* 66h */ { 0 } },
- /* 0x54 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andpd" } },
- /* 0x55 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andnps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andnpd" } },
- /* 0x56 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "orps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "orpd" } },
- /* 0x57 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "xorps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "xorpd" } },
- /* 0x58 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "addps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "addsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "addss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "addpd" } },
- /* 0x59 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "mulps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "mulsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "mulss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "mulpd" } },
- /* 0x5A */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PS, AM_NOT_USED, "cvtps2pd", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "cvtsd2ss" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "cvtss2sd" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PD, AM_NOT_USED, "cvtpd2ps" } },
- /* 0x5B */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2ps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvttps2dq" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvtps2dq" } },
- /* 0x5C */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "subps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "subsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "subss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "subpd" } },
- /* 0x5D */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "minps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "minsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "minss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "minpd" } },
- /* 0x5E */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "divps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "divsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "divss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "divpd" } },
- /* 0x5F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "maxps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "maxsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "maxss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "maxpd" } },
- /* 0x60 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklbw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklbw" } },
- /* 0x61 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklwd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklwd" } },
- /* 0x62 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckldq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpckldq" } },
- /* 0x63 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packsswb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packsswb" } },
- /* 0x64 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtb" } },
- /* 0x65 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtw" } },
- /* 0x66 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtd" } },
- /* 0x67 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packuswb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packuswb" } },
- /* 0x68 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhbw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhbw" } },
- /* 0x69 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhwd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhwd" } },
- /* 0x6A */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhdq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhdq" } },
- /* 0x6B */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packssdw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "packssdw" } },
- /* 0x6C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
- /* 0x6D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
- /* 0x6E */ { 0, IT_GENERIC, AM_P | OT_D, AM_E | OT_D, AM_NOT_USED, "movd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_NOT_USED, "movd" } },
- /* 0x6F */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "movq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqu" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqa" } },
- /* 0x70 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_I | OT_B, "pshuf", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshuflw" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufhw" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufd" } },
- /* 0x71 */ { 19, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x72 */ { 20, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x73 */ { 21, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x74 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqb" } },
- /* 0x75 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqw" } },
- /* 0x76 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqd" } },
- /* 0x77 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "emms", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-
- // The following six opcodes are escapes into the MMX stuff, which this disassembler does not support.
- /* 0x78 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x79 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7A */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7B */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7C */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7D */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-
- /* 0x7E */ { 0, IT_GENERIC, AM_E | OT_D, AM_P | OT_D, AM_NOT_USED, "movd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movq" },
- /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_DQ, AM_NOT_USED, "movd" } },
- /* 0x7F */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_P | OT_Q, AM_NOT_USED, "movq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqu" },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqa" } },
- /* 0x80 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x81 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x82 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x83 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x84 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x85 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x86 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x87 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x88 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x89 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8A */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8B */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8C */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8D */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8E */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8F */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x90 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seto", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x91 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x92 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x93 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x94 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x95 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x96 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x97 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seta", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x98 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "sets", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x99 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9A */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9B */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9C */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9D */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9E */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9F */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cpuid", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA6 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA7 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rsm", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAC */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAD */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAE */ { 22, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB2 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lss", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB4 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lfs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB5 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lgs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB6 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB7 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud1", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBA */ { 23, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBC */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBD */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBE */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC2 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "cmpps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_I | OT_B, "cmpsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_I | OT_B, "cmpss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "cmppd" } },
- /* 0xC3 */ { 0, IT_GENERIC, AM_E | OT_D, AM_G | OT_D, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_E | OT_D, AM_I | OT_B, "pinsrw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_I | OT_B, "pinsrw" } },
- /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_I | OT_B, "pextrw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_I | OT_B, "pextrw" } },
- /* 0xC6 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "shufps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "shufpd" } },
- /* 0xC7 */ { 24, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC8 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC9 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCA */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCB */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCC */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCD */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCE */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCF */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlw" } },
- /* 0xD2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrld", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrld" } },
- /* 0xD3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlq" } },
- /* 0xD4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddq" } },
- /* 0xD5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmullw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmullw" } },
- /* 0xD6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "unused without prefix", true,
- /* F2h */ { 0, IT_GENERIC, AM_P | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movdq2q" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_Q | OT_Q, AM_NOT_USED, "movq2dq" },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movq" } },
- /* 0xD7 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_NOT_USED, "pmovmskb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_NOT_USED, "pmovmskb" } },
- /* 0xD8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusb" } },
- /* 0xD9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusw" } },
- /* 0xDA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminub", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminub" } },
- /* 0xDB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pand", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pand" } },
- /* 0xDC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusb" } },
- /* 0xDD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusw" } },
- /* 0xDE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxub", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxub" } },
- /* 0xDF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pandn", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pandn" } },
- /* 0xE0 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgb" } },
- /* 0xE1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psraw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrqw" } },
- /* 0xE2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrad", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrad" } },
- /* 0xE3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgw" } },
- /* 0xE4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhuw" } },
- /* 0xE5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhw" } },
- /* 0xE6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2dq" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2pd" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2dq" } },
- /* 0xE7 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movntq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movntdq" } },
- /* 0xE8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsb" } },
- /* 0xE9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsw" } },
- /* 0xEA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminsw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminsw" } },
- /* 0xEB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "por", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "por" } },
- /* 0xEC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsb" } },
- /* 0xED */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsw" } },
- /* 0xEE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxsw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxsw" } },
- /* 0xEF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pxor", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pxor" } },
- /* 0xF0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllw" } },
- /* 0xF2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pslld", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pslld" } },
- /* 0xF3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllq" } },
- /* 0xF4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmuludq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmuludq" } },
- /* 0xF5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaddwd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaddwd" } },
- /* 0xF6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psadbw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psadbw" } },
- /* 0xF7 */ { 0, IT_GENERIC, AM_P | OT_PI, AM_Q | OT_PI, AM_NOT_USED, "maskmovq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "maskmovdqu" } },
- /* 0xF8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubb" } },
- /* 0xF9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubw" } },
- /* 0xFA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubd" } },
- /* 0xFB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubq" } },
- /* 0xFC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddb" } },
- /* 0xFD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddw" } },
- /* 0xFE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddd" } },
- /* 0xFF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f00[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "sldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "str", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "ltr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f01[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "smsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lmsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_M | OT_B, AM_NOT_USED, AM_NOT_USED, "invlpg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f18[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f71[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlw" } },
- /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psraw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psraw" } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllw" } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f72[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrld", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrld" } },
- /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrad", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrad" } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "pslld", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslld" } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f73[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlq" } },
- /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllq" } },
- /* 0x7 */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq" } },
-};
-
-const Opcode s_opcode_byte_after_0fae[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxsave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxrstor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ldmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "mfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clflush/sfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-};
-
-const Opcode s_opcode_byte_after_0fba[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0fc7[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_Q, AM_NOT_USED, AM_NOT_USED, "cmpxch8b", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_80[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_81[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_82[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_83[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_c0[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_c1[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_d0[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_d1[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_d2[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_d3[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_f6[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_f7[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_fe[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_ff[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-/*
-* A table of all the other tables, containing some extra information, e.g.
-* how to mask out the byte we're looking at.
-*/
-const OpcodeTable MiniDisassembler::s_ia32_opcode_map_[]={
- // One-byte opcodes and jumps to larger
- /* 0 */ {s_first_opcode_byte, 0, 0xff, 0, 0xff},
- // Two-byte opcodes (second byte)
- /* 1 */ {s_opcode_byte_after_0f, 0, 0xff, 0, 0xff},
- // Start of tables for opcodes using ModR/M bits as extension
- /* 2 */ {s_opcode_byte_after_80, 3, 0x07, 0, 0x07},
- /* 3 */ {s_opcode_byte_after_81, 3, 0x07, 0, 0x07},
- /* 4 */ {s_opcode_byte_after_82, 3, 0x07, 0, 0x07},
- /* 5 */ {s_opcode_byte_after_83, 3, 0x07, 0, 0x07},
- /* 6 */ {s_opcode_byte_after_c0, 3, 0x07, 0, 0x07},
- /* 7 */ {s_opcode_byte_after_c1, 3, 0x07, 0, 0x07},
- /* 8 */ {s_opcode_byte_after_d0, 3, 0x07, 0, 0x07},
- /* 9 */ {s_opcode_byte_after_d1, 3, 0x07, 0, 0x07},
- /* 10 */ {s_opcode_byte_after_d2, 3, 0x07, 0, 0x07},
- /* 11 */ {s_opcode_byte_after_d3, 3, 0x07, 0, 0x07},
- /* 12 */ {s_opcode_byte_after_f6, 3, 0x07, 0, 0x07},
- /* 13 */ {s_opcode_byte_after_f7, 3, 0x07, 0, 0x07},
- /* 14 */ {s_opcode_byte_after_fe, 3, 0x07, 0, 0x01},
- /* 15 */ {s_opcode_byte_after_ff, 3, 0x07, 0, 0x07},
- /* 16 */ {s_opcode_byte_after_0f00, 3, 0x07, 0, 0x07},
- /* 17 */ {s_opcode_byte_after_0f01, 3, 0x07, 0, 0x07},
- /* 18 */ {s_opcode_byte_after_0f18, 3, 0x07, 0, 0x07},
- /* 19 */ {s_opcode_byte_after_0f71, 3, 0x07, 0, 0x07},
- /* 20 */ {s_opcode_byte_after_0f72, 3, 0x07, 0, 0x07},
- /* 21 */ {s_opcode_byte_after_0f73, 3, 0x07, 0, 0x07},
- /* 22 */ {s_opcode_byte_after_0fae, 3, 0x07, 0, 0x07},
- /* 23 */ {s_opcode_byte_after_0fba, 3, 0x07, 0, 0x07},
- /* 24 */ {s_opcode_byte_after_0fc7, 3, 0x07, 0, 0x01}
-};
-
-}; // namespace sidestep
diff --git a/src/third_party/gperftools-2.5/src/windows/mingw.h b/src/third_party/gperftools-2.5/src/windows/mingw.h
deleted file mode 100644
index 0586e624ce1..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/mingw.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-/* Copyright (c) 2007, 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
- *
- * MinGW is an interesting mix of unix and windows. We use a normal
- * configure script, but still need the windows port.h to define some
- * stuff that MinGW doesn't support, like pthreads.
- */
-
-#ifndef GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_
-#define GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_
-
-#ifdef __MINGW32__
-
-// Older version of the mingw msvcrt don't define _aligned_malloc
-#if __MSVCRT_VERSION__ < 0x0700
-# define PERFTOOLS_NO_ALIGNED_MALLOC 1
-#endif
-
-// This must be defined before the windows.h is included. We need at
-// least 0x0400 for mutex.h to have access to TryLock, and at least
-// 0x0501 for patch_functions.cc to have access to GetModuleHandleEx.
-// (This latter is an optimization we could take out if need be.)
-#ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0501
-#endif
-
-#define HAVE_SNPRINTF 1
-
-// Some mingw distributions have a pthreads wrapper, but it doesn't
-// work as well as native windows spinlocks (at least for us). So
-// pretend the pthreads wrapper doesn't exist, even when it does.
-#ifndef HAVE_PTHREAD_DESPITE_ASKING_FOR
-#undef HAVE_PTHREAD
-#endif
-
-#define HAVE_PID_T
-
-#include "windows/port.h"
-
-#endif /* __MINGW32__ */
-
-#endif /* GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_ */
diff --git a/src/third_party/gperftools-2.5/src/windows/mini_disassembler.cc b/src/third_party/gperftools-2.5/src/windows/mini_disassembler.cc
deleted file mode 100644
index 0c620047cec..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/mini_disassembler.cc
+++ /dev/null
@@ -1,432 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2007, 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: Joi Sigurdsson
- *
- * Implementation of MiniDisassembler.
- */
-
-#include "mini_disassembler.h"
-
-namespace sidestep {
-
-MiniDisassembler::MiniDisassembler(bool operand_default_is_32_bits,
- bool address_default_is_32_bits)
- : operand_default_is_32_bits_(operand_default_is_32_bits),
- address_default_is_32_bits_(address_default_is_32_bits) {
- Initialize();
-}
-
-MiniDisassembler::MiniDisassembler()
- : operand_default_is_32_bits_(true),
- address_default_is_32_bits_(true) {
- Initialize();
-}
-
-InstructionType MiniDisassembler::Disassemble(
- unsigned char* start_byte,
- unsigned int& instruction_bytes) {
- // Clean up any state from previous invocations.
- Initialize();
-
- // Start by processing any prefixes.
- unsigned char* current_byte = start_byte;
- unsigned int size = 0;
- InstructionType instruction_type = ProcessPrefixes(current_byte, size);
-
- if (IT_UNKNOWN == instruction_type)
- return instruction_type;
-
- current_byte += size;
- size = 0;
-
- // Invariant: We have stripped all prefixes, and the operand_is_32_bits_
- // and address_is_32_bits_ flags are correctly set.
-
- instruction_type = ProcessOpcode(current_byte, 0, size);
-
- // Check for error processing instruction
- if ((IT_UNKNOWN == instruction_type_) || (IT_UNUSED == instruction_type_)) {
- return IT_UNKNOWN;
- }
-
- current_byte += size;
-
- // Invariant: operand_bytes_ indicates the total size of operands
- // specified by the opcode and/or ModR/M byte and/or SIB byte.
- // pCurrentByte points to the first byte after the ModR/M byte, or after
- // the SIB byte if it is present (i.e. the first byte of any operands
- // encoded in the instruction).
-
- // We get the total length of any prefixes, the opcode, and the ModR/M and
- // SIB bytes if present, by taking the difference of the original starting
- // address and the current byte (which points to the first byte of the
- // operands if present, or to the first byte of the next instruction if
- // they are not). Adding the count of bytes in the operands encoded in
- // the instruction gives us the full length of the instruction in bytes.
- instruction_bytes += operand_bytes_ + (current_byte - start_byte);
-
- // Return the instruction type, which was set by ProcessOpcode().
- return instruction_type_;
-}
-
-void MiniDisassembler::Initialize() {
- operand_is_32_bits_ = operand_default_is_32_bits_;
- address_is_32_bits_ = address_default_is_32_bits_;
-#ifdef _M_X64
- operand_default_support_64_bits_ = true;
-#else
- operand_default_support_64_bits_ = false;
-#endif
- operand_is_64_bits_ = false;
- operand_bytes_ = 0;
- have_modrm_ = false;
- should_decode_modrm_ = false;
- instruction_type_ = IT_UNKNOWN;
- got_f2_prefix_ = false;
- got_f3_prefix_ = false;
- got_66_prefix_ = false;
-}
-
-InstructionType MiniDisassembler::ProcessPrefixes(unsigned char* start_byte,
- unsigned int& size) {
- InstructionType instruction_type = IT_GENERIC;
- const Opcode& opcode = s_ia32_opcode_map_[0].table_[*start_byte];
-
- switch (opcode.type_) {
- case IT_PREFIX_ADDRESS:
- address_is_32_bits_ = !address_default_is_32_bits_;
- goto nochangeoperand;
- case IT_PREFIX_OPERAND:
- operand_is_32_bits_ = !operand_default_is_32_bits_;
- nochangeoperand:
- case IT_PREFIX:
-
- if (0xF2 == (*start_byte))
- got_f2_prefix_ = true;
- else if (0xF3 == (*start_byte))
- got_f3_prefix_ = true;
- else if (0x66 == (*start_byte))
- got_66_prefix_ = true;
- else if (operand_default_support_64_bits_ && (*start_byte) & 0x48)
- operand_is_64_bits_ = true;
-
- instruction_type = opcode.type_;
- size ++;
- // we got a prefix, so add one and check next byte
- ProcessPrefixes(start_byte + 1, size);
- default:
- break; // not a prefix byte
- }
-
- return instruction_type;
-}
-
-InstructionType MiniDisassembler::ProcessOpcode(unsigned char* start_byte,
- unsigned int table_index,
- unsigned int& size) {
- const OpcodeTable& table = s_ia32_opcode_map_[table_index]; // Get our table
- unsigned char current_byte = (*start_byte) >> table.shift_;
- current_byte = current_byte & table.mask_; // Mask out the bits we will use
-
- // Check whether the byte we have is inside the table we have.
- if (current_byte < table.min_lim_ || current_byte > table.max_lim_) {
- instruction_type_ = IT_UNKNOWN;
- return instruction_type_;
- }
-
- const Opcode& opcode = table.table_[current_byte];
- if (IT_UNUSED == opcode.type_) {
- // This instruction is not used by the IA-32 ISA, so we indicate
- // this to the user. Probably means that we were pointed to
- // a byte in memory that was not the start of an instruction.
- instruction_type_ = IT_UNUSED;
- return instruction_type_;
- } else if (IT_REFERENCE == opcode.type_) {
- // We are looking at an opcode that has more bytes (or is continued
- // in the ModR/M byte). Recursively find the opcode definition in
- // the table for the opcode's next byte.
- size++;
- ProcessOpcode(start_byte + 1, opcode.table_index_, size);
- return instruction_type_;
- }
-
- const SpecificOpcode* specific_opcode = (SpecificOpcode*)&opcode;
- if (opcode.is_prefix_dependent_) {
- if (got_f2_prefix_ && opcode.opcode_if_f2_prefix_.mnemonic_ != 0) {
- specific_opcode = &opcode.opcode_if_f2_prefix_;
- } else if (got_f3_prefix_ && opcode.opcode_if_f3_prefix_.mnemonic_ != 0) {
- specific_opcode = &opcode.opcode_if_f3_prefix_;
- } else if (got_66_prefix_ && opcode.opcode_if_66_prefix_.mnemonic_ != 0) {
- specific_opcode = &opcode.opcode_if_66_prefix_;
- }
- }
-
- // Inv: The opcode type is known.
- instruction_type_ = specific_opcode->type_;
-
- // Let's process the operand types to see if we have any immediate
- // operands, and/or a ModR/M byte.
-
- ProcessOperand(specific_opcode->flag_dest_);
- ProcessOperand(specific_opcode->flag_source_);
- ProcessOperand(specific_opcode->flag_aux_);
-
- // Inv: We have processed the opcode and incremented operand_bytes_
- // by the number of bytes of any operands specified by the opcode
- // that are stored in the instruction (not registers etc.). Now
- // we need to return the total number of bytes for the opcode and
- // for the ModR/M or SIB bytes if they are present.
-
- if (table.mask_ != 0xff) {
- if (have_modrm_) {
- // we're looking at a ModR/M byte so we're not going to
- // count that into the opcode size
- ProcessModrm(start_byte, size);
- return IT_GENERIC;
- } else {
- // need to count the ModR/M byte even if it's just being
- // used for opcode extension
- size++;
- return IT_GENERIC;
- }
- } else {
- if (have_modrm_) {
- // The ModR/M byte is the next byte.
- size++;
- ProcessModrm(start_byte + 1, size);
- return IT_GENERIC;
- } else {
- size++;
- return IT_GENERIC;
- }
- }
-}
-
-bool MiniDisassembler::ProcessOperand(int flag_operand) {
- bool succeeded = true;
- if (AM_NOT_USED == flag_operand)
- return succeeded;
-
- // Decide what to do based on the addressing mode.
- switch (flag_operand & AM_MASK) {
- // No ModR/M byte indicated by these addressing modes, and no
- // additional (e.g. immediate) parameters.
- case AM_A: // Direct address
- case AM_F: // EFLAGS register
- case AM_X: // Memory addressed by the DS:SI register pair
- case AM_Y: // Memory addressed by the ES:DI register pair
- case AM_IMPLICIT: // Parameter is implicit, occupies no space in
- // instruction
- break;
-
- // There is a ModR/M byte but it does not necessarily need
- // to be decoded.
- case AM_C: // reg field of ModR/M selects a control register
- case AM_D: // reg field of ModR/M selects a debug register
- case AM_G: // reg field of ModR/M selects a general register
- case AM_P: // reg field of ModR/M selects an MMX register
- case AM_R: // mod field of ModR/M may refer only to a general register
- case AM_S: // reg field of ModR/M selects a segment register
- case AM_T: // reg field of ModR/M selects a test register
- case AM_V: // reg field of ModR/M selects a 128-bit XMM register
- have_modrm_ = true;
- break;
-
- // In these addressing modes, there is a ModR/M byte and it needs to be
- // decoded. No other (e.g. immediate) params than indicated in ModR/M.
- case AM_E: // Operand is either a general-purpose register or memory,
- // specified by ModR/M byte
- case AM_M: // ModR/M byte will refer only to memory
- case AM_Q: // Operand is either an MMX register or memory (complex
- // evaluation), specified by ModR/M byte
- case AM_W: // Operand is either a 128-bit XMM register or memory (complex
- // eval), specified by ModR/M byte
- have_modrm_ = true;
- should_decode_modrm_ = true;
- break;
-
- // These addressing modes specify an immediate or an offset value
- // directly, so we need to look at the operand type to see how many
- // bytes.
- case AM_I: // Immediate data.
- case AM_J: // Jump to offset.
- case AM_O: // Operand is at offset.
- switch (flag_operand & OT_MASK) {
- case OT_B: // Byte regardless of operand-size attribute.
- operand_bytes_ += OS_BYTE;
- break;
- case OT_C: // Byte or word, depending on operand-size attribute.
- if (operand_is_32_bits_)
- operand_bytes_ += OS_WORD;
- else
- operand_bytes_ += OS_BYTE;
- break;
- case OT_D: // Doubleword, regardless of operand-size attribute.
- operand_bytes_ += OS_DOUBLE_WORD;
- break;
- case OT_DQ: // Double-quadword, regardless of operand-size attribute.
- operand_bytes_ += OS_DOUBLE_QUAD_WORD;
- break;
- case OT_P: // 32-bit or 48-bit pointer, depending on operand-size
- // attribute.
- if (operand_is_32_bits_)
- operand_bytes_ += OS_48_BIT_POINTER;
- else
- operand_bytes_ += OS_32_BIT_POINTER;
- break;
- case OT_PS: // 128-bit packed single-precision floating-point data.
- operand_bytes_ += OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING;
- break;
- case OT_Q: // Quadword, regardless of operand-size attribute.
- operand_bytes_ += OS_QUAD_WORD;
- break;
- case OT_S: // 6-byte pseudo-descriptor.
- operand_bytes_ += OS_PSEUDO_DESCRIPTOR;
- break;
- case OT_SD: // Scalar Double-Precision Floating-Point Value
- case OT_PD: // Unaligned packed double-precision floating point value
- operand_bytes_ += OS_DOUBLE_PRECISION_FLOATING;
- break;
- case OT_SS:
- // Scalar element of a 128-bit packed single-precision
- // floating data.
- // We simply return enItUnknown since we don't have to support
- // floating point
- succeeded = false;
- break;
- case OT_V: // Word, doubleword or quadword, depending on operand-size
- // attribute.
- if (operand_is_64_bits_ && flag_operand & AM_I &&
- flag_operand & IOS_64)
- operand_bytes_ += OS_QUAD_WORD;
- else if (operand_is_32_bits_)
- operand_bytes_ += OS_DOUBLE_WORD;
- else
- operand_bytes_ += OS_WORD;
- break;
- case OT_W: // Word, regardless of operand-size attribute.
- operand_bytes_ += OS_WORD;
- break;
-
- // Can safely ignore these.
- case OT_A: // Two one-word operands in memory or two double-word
- // operands in memory
- case OT_PI: // Quadword MMX technology register (e.g. mm0)
- case OT_SI: // Doubleword integer register (e.g., eax)
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- return succeeded;
-}
-
-bool MiniDisassembler::ProcessModrm(unsigned char* start_byte,
- unsigned int& size) {
- // If we don't need to decode, we just return the size of the ModR/M
- // byte (there is never a SIB byte in this case).
- if (!should_decode_modrm_) {
- size++;
- return true;
- }
-
- // We never care about the reg field, only the combination of the mod
- // and r/m fields, so let's start by packing those fields together into
- // 5 bits.
- unsigned char modrm = (*start_byte);
- unsigned char mod = modrm & 0xC0; // mask out top two bits to get mod field
- modrm = modrm & 0x07; // mask out bottom 3 bits to get r/m field
- mod = mod >> 3; // shift the mod field to the right place
- modrm = mod | modrm; // combine the r/m and mod fields as discussed
- mod = mod >> 3; // shift the mod field to bits 2..0
-
- // Invariant: modrm contains the mod field in bits 4..3 and the r/m field
- // in bits 2..0, and mod contains the mod field in bits 2..0
-
- const ModrmEntry* modrm_entry = 0;
- if (address_is_32_bits_)
- modrm_entry = &s_ia32_modrm_map_[modrm];
- else
- modrm_entry = &s_ia16_modrm_map_[modrm];
-
- // Invariant: modrm_entry points to information that we need to decode
- // the ModR/M byte.
-
- // Add to the count of operand bytes, if the ModR/M byte indicates
- // that some operands are encoded in the instruction.
- if (modrm_entry->is_encoded_in_instruction_)
- operand_bytes_ += modrm_entry->operand_size_;
-
- // Process the SIB byte if necessary, and return the count
- // of ModR/M and SIB bytes.
- if (modrm_entry->use_sib_byte_) {
- size++;
- return ProcessSib(start_byte + 1, mod, size);
- } else {
- size++;
- return true;
- }
-}
-
-bool MiniDisassembler::ProcessSib(unsigned char* start_byte,
- unsigned char mod,
- unsigned int& size) {
- // get the mod field from the 2..0 bits of the SIB byte
- unsigned char sib_base = (*start_byte) & 0x07;
- if (0x05 == sib_base) {
- switch (mod) {
- case 0x00: // mod == 00
- case 0x02: // mod == 10
- operand_bytes_ += OS_DOUBLE_WORD;
- break;
- case 0x01: // mod == 01
- operand_bytes_ += OS_BYTE;
- break;
- case 0x03: // mod == 11
- // According to the IA-32 docs, there does not seem to be a disp
- // value for this value of mod
- default:
- break;
- }
- }
-
- size++;
- return true;
-}
-
-}; // namespace sidestep
diff --git a/src/third_party/gperftools-2.5/src/windows/mini_disassembler.h b/src/third_party/gperftools-2.5/src/windows/mini_disassembler.h
deleted file mode 100644
index 93bdc0632ff..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/mini_disassembler.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2007, 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: Joi Sigurdsson
- *
- * Definition of MiniDisassembler.
- */
-
-#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_
-#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_
-
-#include "config.h"
-#include <windows.h>
-#include "mini_disassembler_types.h"
-
-// compatibility shim
-#include "base/logging.h"
-#define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond)
-#define SIDESTEP_LOG(msg) RAW_VLOG(1, msg)
-
-namespace sidestep {
-
-// This small disassembler is very limited
-// in its functionality, and in fact does only the bare minimum required by the
-// preamble patching utility. It may be useful for other purposes, however.
-//
-// The limitations include at least the following:
-// -# No support for coprocessor opcodes, MMX, etc.
-// -# No machine-readable identification of opcodes or decoding of
-// assembly parameters. The name of the opcode (as a string) is given,
-// however, to aid debugging.
-//
-// You may ask what this little disassembler actually does, then? The answer is
-// that it does the following, which is exactly what the patching utility needs:
-// -# Indicates if opcode is a jump (any kind) or a return (any kind)
-// because this is important for the patching utility to determine if
-// a function is too short or there are jumps too early in it for it
-// to be preamble patched.
-// -# The opcode length is always calculated, so that the patching utility
-// can figure out where the next instruction starts, and whether it
-// already has enough instructions to replace with the absolute jump
-// to the patching code.
-//
-// The usage is quite simple; just create a MiniDisassembler and use its
-// Disassemble() method.
-//
-// If you would like to extend this disassembler, please refer to the
-// IA-32 Intel® Architecture Software Developer’s Manual Volume 2:
-// Instruction Set Reference for information about operand decoding
-// etc.
-class PERFTOOLS_DLL_DECL MiniDisassembler {
- public:
-
- // Creates a new instance and sets defaults.
- //
- // @param operand_default_32_bits If true, the default operand size is
- // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
- // @param address_default_32_bits If true, the default address size is
- // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
- MiniDisassembler(bool operand_default_32_bits,
- bool address_default_32_bits);
-
- // Equivalent to MiniDisassembler(true, true);
- MiniDisassembler();
-
- // Attempts to disassemble a single instruction starting from the
- // address in memory it is pointed to.
- //
- // @param start Address where disassembly should start.
- // @param instruction_bytes Variable that will be <b>incremented</b> by
- // the length in bytes of the instruction.
- // @return enItJump, enItReturn or enItGeneric on success. enItUnknown
- // if unable to disassemble, enItUnused if this seems to be an unused
- // opcode. In the last two (error) cases, cbInstruction will be set
- // to 0xffffffff.
- //
- // @post This instance of the disassembler is ready to be used again,
- // with unchanged defaults from creation time.
- InstructionType Disassemble(unsigned char* start, unsigned int& instruction_bytes);
-
- private:
-
- // Makes the disassembler ready for reuse.
- void Initialize();
-
- // Sets the flags for address and operand sizes.
- // @return Number of prefix bytes.
- InstructionType ProcessPrefixes(unsigned char* start, unsigned int& size);
-
- // Sets the flag for whether we have ModR/M, and increments
- // operand_bytes_ if any are specifies by the opcode directly.
- // @return Number of opcode bytes.
- InstructionType ProcessOpcode(unsigned char* start,
- unsigned int table,
- unsigned int& size);
-
- // Checks the type of the supplied operand. Increments
- // operand_bytes_ if it directly indicates an immediate etc.
- // operand. Asserts have_modrm_ if the operand specifies
- // a ModR/M byte.
- bool ProcessOperand(int flag_operand);
-
- // Increments operand_bytes_ by size specified by ModR/M and
- // by SIB if present.
- // @return 0 in case of error, 1 if there is just a ModR/M byte,
- // 2 if there is a ModR/M byte and a SIB byte.
- bool ProcessModrm(unsigned char* start, unsigned int& size);
-
- // Processes the SIB byte that it is pointed to.
- // @param start Pointer to the SIB byte.
- // @param mod The mod field from the ModR/M byte.
- // @return 1 to indicate success (indicates 1 SIB byte)
- bool ProcessSib(unsigned char* start, unsigned char mod, unsigned int& size);
-
- // The instruction type we have decoded from the opcode.
- InstructionType instruction_type_;
-
- // Counts the number of bytes that is occupied by operands in
- // the current instruction (note: we don't care about how large
- // operands stored in registers etc. are).
- unsigned int operand_bytes_;
-
- // True iff there is a ModR/M byte in this instruction.
- bool have_modrm_;
-
- // True iff we need to decode the ModR/M byte (sometimes it just
- // points to a register, we can tell by the addressing mode).
- bool should_decode_modrm_;
-
- // Current operand size is 32 bits if true, 16 bits if false.
- bool operand_is_32_bits_;
-
- // Default operand size is 32 bits if true, 16 bits if false.
- bool operand_default_is_32_bits_;
-
- // Current address size is 32 bits if true, 16 bits if false.
- bool address_is_32_bits_;
-
- // Default address size is 32 bits if true, 16 bits if false.
- bool address_default_is_32_bits_;
-
- // Determines if 64 bit operands are supported (x64).
- bool operand_default_support_64_bits_;
-
- // Current operand size is 64 bits if true, 32 bits if false.
- bool operand_is_64_bits_;
-
- // Huge big opcode table based on the IA-32 manual, defined
- // in Ia32OpcodeMap.cc
- static const OpcodeTable s_ia32_opcode_map_[];
-
- // Somewhat smaller table to help with decoding ModR/M bytes
- // when 16-bit addressing mode is being used. Defined in
- // Ia32ModrmMap.cc
- static const ModrmEntry s_ia16_modrm_map_[];
-
- // Somewhat smaller table to help with decoding ModR/M bytes
- // when 32-bit addressing mode is being used. Defined in
- // Ia32ModrmMap.cc
- static const ModrmEntry s_ia32_modrm_map_[];
-
- // Indicators of whether we got certain prefixes that certain
- // silly Intel instructions depend on in nonstandard ways for
- // their behaviors.
- bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_;
-};
-
-}; // namespace sidestep
-
-#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_
diff --git a/src/third_party/gperftools-2.5/src/windows/mini_disassembler_types.h b/src/third_party/gperftools-2.5/src/windows/mini_disassembler_types.h
deleted file mode 100644
index 06d475504e4..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/mini_disassembler_types.h
+++ /dev/null
@@ -1,237 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2007, 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: Joi Sigurdsson
- *
- * Several simple types used by the disassembler and some of the patching
- * mechanisms.
- */
-
-#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H_
-#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H_
-
-namespace sidestep {
-
-// Categories of instructions that we care about
-enum InstructionType {
- // This opcode is not used
- IT_UNUSED,
- // This disassembler does not recognize this opcode (error)
- IT_UNKNOWN,
- // This is not an instruction but a reference to another table
- IT_REFERENCE,
- // This byte is a prefix byte that we can ignore
- IT_PREFIX,
- // This is a prefix byte that switches to the nondefault address size
- IT_PREFIX_ADDRESS,
- // This is a prefix byte that switches to the nondefault operand size
- IT_PREFIX_OPERAND,
- // A jump or call instruction
- IT_JUMP,
- // A return instruction
- IT_RETURN,
- // Any other type of instruction (in this case we don't care what it is)
- IT_GENERIC,
-};
-
-// Lists IA-32 operand sizes in multiples of 8 bits
-enum OperandSize {
- OS_ZERO = 0,
- OS_BYTE = 1,
- OS_WORD = 2,
- OS_DOUBLE_WORD = 4,
- OS_QUAD_WORD = 8,
- OS_DOUBLE_QUAD_WORD = 16,
- OS_32_BIT_POINTER = 32/8,
- OS_48_BIT_POINTER = 48/8,
- OS_SINGLE_PRECISION_FLOATING = 32/8,
- OS_DOUBLE_PRECISION_FLOATING = 64/8,
- OS_DOUBLE_EXTENDED_PRECISION_FLOATING = 80/8,
- OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING = 128/8,
- OS_PSEUDO_DESCRIPTOR = 6
-};
-
-// Operand addressing methods from the IA-32 manual. The enAmMask value
-// is a mask for the rest. The other enumeration values are named for the
-// names given to the addressing methods in the manual, e.g. enAm_D is for
-// the D addressing method.
-//
-// The reason we use a full 4 bytes and a mask, is that we need to combine
-// these flags with the enOperandType to store the details
-// on the operand in a single integer.
-enum AddressingMethod {
- AM_NOT_USED = 0, // This operand is not used for this instruction
- AM_MASK = 0x00FF0000, // Mask for the rest of the values in this enumeration
- AM_A = 0x00010000, // A addressing type
- AM_C = 0x00020000, // C addressing type
- AM_D = 0x00030000, // D addressing type
- AM_E = 0x00040000, // E addressing type
- AM_F = 0x00050000, // F addressing type
- AM_G = 0x00060000, // G addressing type
- AM_I = 0x00070000, // I addressing type
- AM_J = 0x00080000, // J addressing type
- AM_M = 0x00090000, // M addressing type
- AM_O = 0x000A0000, // O addressing type
- AM_P = 0x000B0000, // P addressing type
- AM_Q = 0x000C0000, // Q addressing type
- AM_R = 0x000D0000, // R addressing type
- AM_S = 0x000E0000, // S addressing type
- AM_T = 0x000F0000, // T addressing type
- AM_V = 0x00100000, // V addressing type
- AM_W = 0x00110000, // W addressing type
- AM_X = 0x00120000, // X addressing type
- AM_Y = 0x00130000, // Y addressing type
- AM_REGISTER = 0x00140000, // Specific register is always used as this op
- AM_IMPLICIT = 0x00150000, // An implicit, fixed value is used
-};
-
-// Operand types from the IA-32 manual. The enOtMask value is
-// a mask for the rest. The rest of the values are named for the
-// names given to these operand types in the manual, e.g. enOt_ps
-// is for the ps operand type in the manual.
-//
-// The reason we use a full 4 bytes and a mask, is that we need
-// to combine these flags with the enAddressingMethod to store the details
-// on the operand in a single integer.
-enum OperandType {
- OT_MASK = 0xFF000000,
- OT_A = 0x01000000,
- OT_B = 0x02000000,
- OT_C = 0x03000000,
- OT_D = 0x04000000,
- OT_DQ = 0x05000000,
- OT_P = 0x06000000,
- OT_PI = 0x07000000,
- OT_PS = 0x08000000, // actually unsupported for (we don't know its size)
- OT_Q = 0x09000000,
- OT_S = 0x0A000000,
- OT_SS = 0x0B000000,
- OT_SI = 0x0C000000,
- OT_V = 0x0D000000,
- OT_W = 0x0E000000,
- OT_SD = 0x0F000000, // scalar double-precision floating-point value
- OT_PD = 0x10000000, // double-precision floating point
- // dummy "operand type" for address mode M - which doesn't specify
- // operand type
- OT_ADDRESS_MODE_M = 0x80000000
-};
-
-// Flag that indicates if an immediate operand is 64-bits.
-//
-// The Intel 64 and IA-32 Architecture Software Developer's Manual currently
-// defines MOV as the only instruction supporting a 64-bit immediate operand.
-enum ImmediateOperandSize {
- IOS_MASK = 0x0000F000,
- IOS_DEFAULT = 0x0,
- IOS_64 = 0x00001000
-};
-
-// Everything that's in an Opcode (see below) except the three
-// alternative opcode structs for different prefixes.
-struct SpecificOpcode {
- // Index to continuation table, or 0 if this is the last
- // byte in the opcode.
- int table_index_;
-
- // The opcode type
- InstructionType type_;
-
- // Description of the type of the dest, src and aux operands,
- // put together from enOperandType, enAddressingMethod and
- // enImmediateOperandSize flags.
- int flag_dest_;
- int flag_source_;
- int flag_aux_;
-
- // We indicate the mnemonic for debugging purposes
- const char* mnemonic_;
-};
-
-// The information we keep in our tables about each of the different
-// valid instructions recognized by the IA-32 architecture.
-struct Opcode {
- // Index to continuation table, or 0 if this is the last
- // byte in the opcode.
- int table_index_;
-
- // The opcode type
- InstructionType type_;
-
- // Description of the type of the dest, src and aux operands,
- // put together from an enOperandType flag and an enAddressingMethod
- // flag.
- int flag_dest_;
- int flag_source_;
- int flag_aux_;
-
- // We indicate the mnemonic for debugging purposes
- const char* mnemonic_;
-
- // Alternative opcode info if certain prefixes are specified.
- // In most cases, all of these are zeroed-out. Only used if
- // bPrefixDependent is true.
- bool is_prefix_dependent_;
- SpecificOpcode opcode_if_f2_prefix_;
- SpecificOpcode opcode_if_f3_prefix_;
- SpecificOpcode opcode_if_66_prefix_;
-};
-
-// Information about each table entry.
-struct OpcodeTable {
- // Table of instruction entries
- const Opcode* table_;
- // How many bytes left to shift ModR/M byte <b>before</b> applying mask
- unsigned char shift_;
- // Mask to apply to byte being looked at before comparing to table
- unsigned char mask_;
- // Minimum/maximum indexes in table.
- unsigned char min_lim_;
- unsigned char max_lim_;
-};
-
-// Information about each entry in table used to decode ModR/M byte.
-struct ModrmEntry {
- // Is the operand encoded as bytes in the instruction (rather than
- // if it's e.g. a register in which case it's just encoded in the
- // ModR/M byte)
- bool is_encoded_in_instruction_;
-
- // Is there a SIB byte? In this case we always need to decode it.
- bool use_sib_byte_;
-
- // What is the size of the operand (only important if it's encoded
- // in the instruction)?
- OperandSize operand_size_;
-};
-
-}; // namespace sidestep
-
-#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H_
diff --git a/src/third_party/gperftools-2.5/src/windows/nm-pdb.c b/src/third_party/gperftools-2.5/src/windows/nm-pdb.c
deleted file mode 100644
index 95a080d6859..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/nm-pdb.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/* 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: David Vitek
- *
- * Dump function addresses using Microsoft debug symbols. This works
- * on PDB files. Note that this program will download symbols to
- * c:\websymbols without asking.
- */
-
-#define WIN32_LEAN_AND_MEAN
-#define _CRT_SECURE_NO_WARNINGS
-#define _CRT_SECURE_NO_DEPRECATE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h> // for _strdup
-
-#include <windows.h>
-#include <dbghelp.h>
-
-// Unfortunately, there is no versioning info in dbghelp.h so I can
-// tell whether it has an old-style (circa VC7.1) IMAGEHLP_MODULE64
-// struct, with only a few fields, or a new-style (circa VC8)
-// IMAGEHLP_MODULE64, with lots of fields. These fields are just used
-// for debugging, so it's fine to just assume the smaller struct, but
-// for most people, using a modern MSVC, the full struct is available.
-// If you are one of those people and would like this extra debugging
-// info, you can uncomment the line below.
-//#define VC8_OR_ABOVE
-
-#define SEARCH_CAP (1024*1024)
-#define WEBSYM "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols"
-
-typedef struct {
- char *name;
- ULONG64 addr;
- ULONG flags;
-} SYM;
-
-typedef struct {
- ULONG64 module_base;
- SYM *syms;
- DWORD syms_len;
- DWORD syms_cap;
-} SYM_CONTEXT;
-
-static int sym_cmp(const void *_s1, const void *_s2) {
- const SYM *s1 = (const SYM *)_s1;
- const SYM *s2 = (const SYM *)_s2;
-
- if (s1->addr < s2->addr)
- return -1;
- if (s1->addr > s2->addr)
- return 1;
- return 0;
-}
-
-static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO symbol_info,
- ULONG symbol_size,
- PVOID user_context) {
- SYM_CONTEXT *ctx = (SYM_CONTEXT*)user_context;
- if (symbol_info->Address < ctx->module_base ||
- (symbol_info->Flags & SYMFLAG_TLSREL)) {
- return TRUE;
- }
- if (ctx->syms_len == ctx->syms_cap) {
- if (!ctx->syms_cap)
- ctx->syms_cap++;
- ctx->syms_cap *= 2;
- ctx->syms = realloc(ctx->syms, sizeof(ctx->syms[0]) * ctx->syms_cap);
- }
- ctx->syms[ctx->syms_len].name = _strdup(symbol_info->Name);
- ctx->syms[ctx->syms_len].addr = symbol_info->Address;
- ctx->syms[ctx->syms_len].flags = symbol_info->Flags;
- ctx->syms_len++;
- return TRUE;
-}
-
-static void MaybePrint(const char* var, const char* description) {
- if (var[0])
- printf("%s: %s\n", description, var);
-}
-
-static void PrintAvailability(BOOL var, const char *description) {
- printf("%s: %s\n", description, (var ? "Available" : "Not available"));
-}
-
-static void ShowSymbolInfo(HANDLE process, ULONG64 module_base) {
- /* Get module information. */
- IMAGEHLP_MODULE64 module_info;
- BOOL getmoduleinfo_rv;
- printf("Load Address: %I64x\n", module_base);
- memset(&module_info, 0, sizeof(module_info));
- module_info.SizeOfStruct = sizeof(module_info);
- getmoduleinfo_rv = SymGetModuleInfo64(process, module_base, &module_info);
- if (!getmoduleinfo_rv) {
- printf("Error: SymGetModuleInfo64() failed. Error code: %u\n",
- GetLastError());
- return;
- }
- /* Display information about symbols, based on kind of symbol. */
- switch (module_info.SymType) {
- case SymNone:
- printf(("No symbols available for the module.\n"));
- break;
- case SymExport:
- printf(("Loaded symbols: Exports\n"));
- break;
- case SymCoff:
- printf(("Loaded symbols: COFF\n"));
- break;
- case SymCv:
- printf(("Loaded symbols: CodeView\n"));
- break;
- case SymSym:
- printf(("Loaded symbols: SYM\n"));
- break;
- case SymVirtual:
- printf(("Loaded symbols: Virtual\n"));
- break;
- case SymPdb:
- printf(("Loaded symbols: PDB\n"));
- break;
- case SymDia:
- printf(("Loaded symbols: DIA\n"));
- break;
- case SymDeferred:
- printf(("Loaded symbols: Deferred\n")); /* not actually loaded */
- break;
- default:
- printf(("Loaded symbols: Unknown format.\n"));
- break;
- }
-
- MaybePrint("Image name", module_info.ImageName);
- MaybePrint("Loaded image name", module_info.LoadedImageName);
-#ifdef VC8_OR_ABOVE /* TODO(csilvers): figure out how to tell */
- MaybePrint("PDB file name", module_info.LoadedPdbName);
- if (module_info.PdbUnmatched || module_info.DbgUnmatched) {
- /* This can only happen if the debug information is contained in a
- * separate file (.DBG or .PDB)
- */
- printf(("Warning: Unmatched symbols.\n"));
- }
-#endif
-
- /* Contents */
-#ifdef VC8_OR_ABOVE /* TODO(csilvers): figure out how to tell */
- PrintAvailability("Line numbers", module_info.LineNumbers);
- PrintAvailability("Global symbols", module_info.GlobalSymbols);
- PrintAvailability("Type information", module_info.TypeInfo);
-#endif
-}
-
-void usage() {
- fprintf(stderr, "usage: nm-pdb [-C|--demangle] <module or filename>\n");
-}
-
-int main(int argc, char *argv[]) {
- DWORD error;
- HANDLE process;
- ULONG64 module_base;
- SYM_CONTEXT ctx;
- int i;
- char* search;
- char* filename = NULL;
- int rv = 0;
- /* We may add SYMOPT_UNDNAME if --demangle is specified: */
- DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG;
-
- for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "--demangle") == 0 || strcmp(argv[i], "-C") == 0) {
- symopts |= SYMOPT_UNDNAME;
- } else if (strcmp(argv[i], "--help") == 0) {
- usage();
- exit(0);
- } else {
- break;
- }
- }
- if (i != argc - 1) {
- usage();
- exit(1);
- }
- filename = argv[i];
-
- process = GetCurrentProcess();
-
- if (!SymInitialize(process, NULL, FALSE)) {
- error = GetLastError();
- fprintf(stderr, "SymInitialize returned error : %d\n", error);
- return 1;
- }
-
- search = malloc(SEARCH_CAP);
- if (SymGetSearchPath(process, search, SEARCH_CAP)) {
- if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) {
- fprintf(stderr, "Search path too long\n");
- SymCleanup(process);
- return 1;
- }
- strcat(search, ";" WEBSYM);
- } else {
- error = GetLastError();
- fprintf(stderr, "SymGetSearchPath returned error : %d\n", error);
- rv = 1; /* An error, but not a fatal one */
- strcpy(search, WEBSYM); /* Use a default value */
- }
- if (!SymSetSearchPath(process, search)) {
- error = GetLastError();
- fprintf(stderr, "SymSetSearchPath returned error : %d\n", error);
- rv = 1; /* An error, but not a fatal one */
- }
-
- SymSetOptions(symopts);
- module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0);
- if (!module_base) {
- /* SymLoadModuleEx failed */
- error = GetLastError();
- fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n",
- error, filename);
- SymCleanup(process);
- return 1;
- }
-
- ShowSymbolInfo(process, module_base);
-
- memset(&ctx, 0, sizeof(ctx));
- ctx.module_base = module_base;
- if (!SymEnumSymbols(process, module_base, NULL, EnumSymProc, &ctx)) {
- error = GetLastError();
- fprintf(stderr, "SymEnumSymbols returned error: %d\n", error);
- rv = 1;
- } else {
- DWORD j;
- qsort(ctx.syms, ctx.syms_len, sizeof(ctx.syms[0]), sym_cmp);
- for (j = 0; j < ctx.syms_len; j++) {
- printf("%016I64x X %s\n", ctx.syms[j].addr, ctx.syms[j].name);
- }
- /* In a perfect world, maybe we'd clean up ctx's memory? */
- }
- SymUnloadModule64(process, module_base);
- SymCleanup(process);
- return rv;
-}
diff --git a/src/third_party/gperftools-2.5/src/windows/override_functions.cc b/src/third_party/gperftools-2.5/src/windows/override_functions.cc
deleted file mode 100644
index e7917d3a7b6..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/override_functions.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, 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: Mike Belshe
-//
-// To link tcmalloc into a EXE or DLL statically without using the patching
-// facility, we can take a stock libcmt and remove all the allocator functions.
-// When we relink the EXE/DLL with the modified libcmt and tcmalloc, a few
-// functions are missing. This file contains the additional overrides which
-// are required in the VS2005 libcmt in order to link the modified libcmt.
-//
-// See also
-// http://groups.google.com/group/google-perftools/browse_thread/thread/41cd3710af85e57b
-
-#include <config.h>
-
-#ifndef _WIN32
-# error You should only be including this file in a windows environment!
-#endif
-
-#ifndef WIN32_OVERRIDE_ALLOCATORS
-# error This file is intended for use when overriding allocators
-#endif
-
-#include "tcmalloc.cc"
-
-extern "C" void* _recalloc(void* p, size_t n, size_t size) {
- void* result = realloc(p, n * size);
- memset(result, 0, n * size);
- return result;
-}
-
-extern "C" void* _calloc_impl(size_t n, size_t size) {
- return calloc(n, size);
-}
-
-extern "C" size_t _msize(void* p) {
- return MallocExtension::instance()->GetAllocatedSize(p);
-}
-
-extern "C" intptr_t _get_heap_handle() {
- return 0;
-}
-
-// The CRT heap initialization stub.
-extern "C" int _heap_init() {
- // We intentionally leak this object. It lasts for the process
- // lifetime. Trying to teardown at _heap_term() is so late that
- // you can't do anything useful anyway.
- new TCMallocGuard();
- return 1;
-}
-
-// The CRT heap cleanup stub.
-extern "C" void _heap_term() {
-}
-
-extern "C" int _set_new_mode(int flag) {
- return tc_set_new_mode(flag);
-}
-
-#ifndef NDEBUG
-#undef malloc
-#undef free
-#undef calloc
-int _CrtDbgReport(int, const char*, int, const char*, const char*, ...) {
- return 0;
-}
-
-int _CrtDbgReportW(int, const wchar_t*, int, const wchar_t*, const wchar_t*, ...) {
- return 0;
-}
-
-int _CrtSetReportMode(int, int) {
- return 0;
-}
-
-extern "C" void* _malloc_dbg(size_t size, int , const char*, int) {
- return malloc(size);
-}
-
-extern "C" void _free_dbg(void* ptr, int) {
- free(ptr);
-}
-
-extern "C" void* _calloc_dbg(size_t n, size_t size, int, const char*, int) {
- return calloc(n, size);
-}
-#endif // NDEBUG
-
-// We set this to 1 because part of the CRT uses a check of _crtheap != 0
-// to test whether the CRT has been initialized. Once we've ripped out
-// the allocators from libcmt, we need to provide this definition so that
-// the rest of the CRT is still usable.
-extern "C" void* _crtheap = reinterpret_cast<void*>(1);
diff --git a/src/third_party/gperftools-2.5/src/windows/patch_functions.cc b/src/third_party/gperftools-2.5/src/windows/patch_functions.cc
deleted file mode 100644
index 70771d2911b..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/patch_functions.cc
+++ /dev/null
@@ -1,1088 +0,0 @@
-// Copyright (c) 2007, 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
-//
-// The main purpose of this file is to patch the libc allocation
-// routines (malloc and friends, but also _msize and other
-// windows-specific libc-style routines). However, we also patch
-// windows routines to do accounting. We do better at the former than
-// the latter. Here are some comments from Paul Pluzhnikov about what
-// it might take to do a really good job patching windows routines to
-// keep track of memory usage:
-//
-// "You should intercept at least the following:
-// HeapCreate HeapDestroy HeapAlloc HeapReAlloc HeapFree
-// RtlCreateHeap RtlDestroyHeap RtlAllocateHeap RtlFreeHeap
-// malloc calloc realloc free
-// malloc_dbg calloc_dbg realloc_dbg free_dbg
-// Some of these call the other ones (but not always), sometimes
-// recursively (i.e. HeapCreate may call HeapAlloc on a different
-// heap, IIRC)."
-//
-// Since Paul didn't mention VirtualAllocEx, he may not have even been
-// considering all the mmap-like functions that windows has (or he may
-// just be ignoring it because he's seen we already patch it). Of the
-// above, we do not patch the *_dbg functions, and of the windows
-// functions, we only patch HeapAlloc and HeapFree.
-//
-// The *_dbg functions come into play with /MDd, /MTd, and /MLd,
-// probably. It may be ok to just turn off tcmalloc in those cases --
-// if the user wants the windows debug malloc, they probably don't
-// want tcmalloc! We should also test with all of /MD, /MT, and /ML,
-// which we're not currently doing.
-
-// TODO(csilvers): try to do better here? Paul does conclude:
-// "Keeping track of all of this was a nightmare."
-
-#ifndef _WIN32
-# error You should only be including windows/patch_functions.cc in a windows environment!
-#endif
-
-#include <config.h>
-
-#ifdef WIN32_OVERRIDE_ALLOCATORS
-#error This file is intended for patching allocators - use override_functions.cc instead.
-#endif
-
-// We use psapi. Non-MSVC systems will have to link this in themselves.
-#ifdef _MSC_VER
-#pragma comment(lib, "Psapi.lib")
-#endif
-
-// Make sure we always use the 'old' names of the psapi functions.
-#ifndef PSAPI_VERSION
-#define PSAPI_VERSION 1
-#endif
-
-#include <windows.h>
-#include <stdio.h>
-#include <malloc.h> // for _msize and _expand
-#include <psapi.h> // for EnumProcessModules, GetModuleInformation, etc.
-#include <set>
-#include <map>
-#include <vector>
-#include <base/logging.h>
-#include "base/spinlock.h"
-#include "gperftools/malloc_hook.h"
-#include "malloc_hook-inl.h"
-#include "preamble_patcher.h"
-
-// The maximum number of modules we allow to be in one executable
-const int kMaxModules = 8182;
-
-// These are hard-coded, unfortunately. :-( They are also probably
-// compiler specific. See get_mangled_names.cc, in this directory,
-// for instructions on how to update these names for your compiler.
-#ifdef _WIN64
-const char kMangledNew[] = "??2@YAPEAX_K@Z";
-const char kMangledNewArray[] = "??_U@YAPEAX_K@Z";
-const char kMangledDelete[] = "??3@YAXPEAX@Z";
-const char kMangledDeleteArray[] = "??_V@YAXPEAX@Z";
-const char kMangledNewNothrow[] = "??2@YAPEAX_KAEBUnothrow_t@std@@@Z";
-const char kMangledNewArrayNothrow[] = "??_U@YAPEAX_KAEBUnothrow_t@std@@@Z";
-const char kMangledDeleteNothrow[] = "??3@YAXPEAXAEBUnothrow_t@std@@@Z";
-const char kMangledDeleteArrayNothrow[] = "??_V@YAXPEAXAEBUnothrow_t@std@@@Z";
-#else
-const char kMangledNew[] = "??2@YAPAXI@Z";
-const char kMangledNewArray[] = "??_U@YAPAXI@Z";
-const char kMangledDelete[] = "??3@YAXPAX@Z";
-const char kMangledDeleteArray[] = "??_V@YAXPAX@Z";
-const char kMangledNewNothrow[] = "??2@YAPAXIABUnothrow_t@std@@@Z";
-const char kMangledNewArrayNothrow[] = "??_U@YAPAXIABUnothrow_t@std@@@Z";
-const char kMangledDeleteNothrow[] = "??3@YAXPAXABUnothrow_t@std@@@Z";
-const char kMangledDeleteArrayNothrow[] = "??_V@YAXPAXABUnothrow_t@std@@@Z";
-#endif
-
-// This is an unused but exported symbol that we can use to tell the
-// MSVC linker to bring in libtcmalloc, via the /INCLUDE linker flag.
-// Without this, the linker will likely decide that libtcmalloc.dll
-// doesn't add anything to the executable (since it does all its work
-// through patching, which the linker can't see), and ignore it
-// entirely. (The name 'tcmalloc' is already reserved for a
-// namespace. I'd rather export a variable named "_tcmalloc", but I
-// couldn't figure out how to get that to work. This function exports
-// the symbol "__tcmalloc".)
-extern "C" PERFTOOLS_DLL_DECL void _tcmalloc();
-void _tcmalloc() { }
-
-// This is the version needed for windows x64, which has a different
-// decoration scheme which doesn't auto-add a leading underscore.
-extern "C" PERFTOOLS_DLL_DECL void __tcmalloc();
-void __tcmalloc() { }
-
-namespace { // most everything here is in an unnamed namespace
-
-typedef void (*GenericFnPtr)();
-
-using sidestep::PreamblePatcher;
-
-struct ModuleEntryCopy; // defined below
-
-// These functions are how we override the memory allocation
-// functions, just like tcmalloc.cc and malloc_hook.cc do.
-
-// This is information about the routines we're patching, for a given
-// module that implements libc memory routines. A single executable
-// can have several libc implementations running about (in different
-// .dll's), and we need to patch/unpatch them all. This defines
-// everything except the new functions we're patching in, which
-// are defined in LibcFunctions, below.
-class LibcInfo {
- public:
- LibcInfo() {
- memset(this, 0, sizeof(*this)); // easiest way to initialize the array
- }
-
- bool patched() const { return is_valid(); }
- void set_is_valid(bool b) { is_valid_ = b; }
- // According to http://msdn.microsoft.com/en-us/library/ms684229(VS.85).aspx:
- // "The load address of a module (lpBaseOfDll) is the same as the HMODULE
- // value."
- HMODULE hmodule() const {
- return reinterpret_cast<HMODULE>(const_cast<void*>(module_base_address_));
- }
-
- // Populates all the windows_fn_[] vars based on our module info.
- // Returns false if windows_fn_ is all NULL's, because there's
- // nothing to patch. Also populates the rest of the module_entry
- // info, such as the module's name.
- bool PopulateWindowsFn(const ModuleEntryCopy& module_entry);
-
- protected:
- void CopyFrom(const LibcInfo& that) {
- if (this == &that)
- return;
- this->is_valid_ = that.is_valid_;
- memcpy(this->windows_fn_, that.windows_fn_, sizeof(windows_fn_));
- this->module_base_address_ = that.module_base_address_;
- this->module_base_size_ = that.module_base_size_;
- }
-
- enum {
- kMalloc, kFree, kRealloc, kCalloc,
- kNew, kNewArray, kDelete, kDeleteArray,
- kNewNothrow, kNewArrayNothrow, kDeleteNothrow, kDeleteArrayNothrow,
- // These are windows-only functions from malloc.h
- k_Msize, k_Expand,
- // A MS CRT "internal" function, implemented using _calloc_impl
- k_CallocCrt,
- kNumFunctions
- };
-
- // I'd like to put these together in a struct (perhaps in the
- // subclass, so we can put in perftools_fn_ as well), but vc8 seems
- // to have a bug where it doesn't initialize the struct properly if
- // we try to take the address of a function that's not yet loaded
- // from a dll, as is the common case for static_fn_. So we need
- // each to be in its own array. :-(
- static const char* const function_name_[kNumFunctions];
-
- // This function is only used when statically linking the binary.
- // In that case, loading malloc/etc from the dll (via
- // PatchOneModule) won't work, since there are no dlls. Instead,
- // you just want to be taking the address of malloc/etc directly.
- // In the common, non-static-link case, these pointers will all be
- // NULL, since this initializer runs before msvcrt.dll is loaded.
- static const GenericFnPtr static_fn_[kNumFunctions];
-
- // This is the address of the function we are going to patch
- // (malloc, etc). Other info about the function is in the
- // patch-specific subclasses, below.
- GenericFnPtr windows_fn_[kNumFunctions];
-
- // This is set to true when this structure is initialized (because
- // we're patching a new library) and set to false when it's
- // uninitialized (because we've freed that library).
- bool is_valid_;
-
- const void *module_base_address_;
- size_t module_base_size_;
-
- public:
- // These shouldn't have to be public, since only subclasses of
- // LibcInfo need it, but they do. Maybe something to do with
- // templates. Shrug. I hide them down here so users won't see
- // them. :-) (OK, I also need to define ctrgProcAddress late.)
- bool is_valid() const { return is_valid_; }
- GenericFnPtr windows_fn(int ifunction) const {
- return windows_fn_[ifunction];
- }
- // These three are needed by ModuleEntryCopy.
- static const int ctrgProcAddress = kNumFunctions;
- static GenericFnPtr static_fn(int ifunction) {
- return static_fn_[ifunction];
- }
- static const char* const function_name(int ifunction) {
- return function_name_[ifunction];
- }
-};
-
-// Template trickiness: logically, a LibcInfo would include
-// Windows_malloc_, origstub_malloc_, and Perftools_malloc_: for a
-// given module, these three go together. And in fact,
-// Perftools_malloc_ may need to call origstub_malloc_, which means we
-// either need to change Perftools_malloc_ to take origstub_malloc_ as
-// an argument -- unfortunately impossible since it needs to keep the
-// same API as normal malloc -- or we need to write a different
-// version of Perftools_malloc_ for each LibcInfo instance we create.
-// We choose the second route, and use templates to implement it (we
-// could have also used macros). So to get multiple versions
-// of the struct, we say "struct<1> var1; struct<2> var2;". The price
-// we pay is some code duplication, and more annoying, each instance
-// of this var is a separate type.
-template<int> class LibcInfoWithPatchFunctions : public LibcInfo {
- public:
- // me_info should have had PopulateWindowsFn() called on it, so the
- // module_* vars and windows_fn_ are set up.
- bool Patch(const LibcInfo& me_info);
- void Unpatch();
-
- private:
- // This holds the original function contents after we patch the function.
- // This has to be defined static in the subclass, because the perftools_fns
- // reference origstub_fn_.
- static GenericFnPtr origstub_fn_[kNumFunctions];
-
- // This is the function we want to patch in
- static const GenericFnPtr perftools_fn_[kNumFunctions];
-
- static void* Perftools_malloc(size_t size) __THROW;
- static void Perftools_free(void* ptr) __THROW;
- static void* Perftools_realloc(void* ptr, size_t size) __THROW;
- static void* Perftools_calloc(size_t nmemb, size_t size) __THROW;
- static void* Perftools_new(size_t size);
- static void* Perftools_newarray(size_t size);
- static void Perftools_delete(void *ptr);
- static void Perftools_deletearray(void *ptr);
- static void* Perftools_new_nothrow(size_t size,
- const std::nothrow_t&) __THROW;
- static void* Perftools_newarray_nothrow(size_t size,
- const std::nothrow_t&) __THROW;
- static void Perftools_delete_nothrow(void *ptr,
- const std::nothrow_t&) __THROW;
- static void Perftools_deletearray_nothrow(void *ptr,
- const std::nothrow_t&) __THROW;
- static size_t Perftools__msize(void *ptr) __THROW;
- static void* Perftools__expand(void *ptr, size_t size) __THROW;
- // malloc.h also defines these functions:
- // _aligned_malloc, _aligned_free,
- // _recalloc, _aligned_offset_malloc, _aligned_realloc, _aligned_recalloc
- // _aligned_offset_realloc, _aligned_offset_recalloc, _malloca, _freea
- // But they seem pretty obscure, and I'm fine not overriding them for now.
- // It may be they all call into malloc/free anyway.
-};
-
-// This is a subset of MODDULEENTRY32, that we need for patching.
-struct ModuleEntryCopy {
- LPVOID modBaseAddr; // the same as hmodule
- DWORD modBaseSize;
- // This is not part of MODDULEENTRY32, but is needed to avoid making
- // windows syscalls while we're holding patch_all_modules_lock (see
- // lock-inversion comments at patch_all_modules_lock definition, below).
- GenericFnPtr rgProcAddresses[LibcInfo::ctrgProcAddress];
-
- ModuleEntryCopy() {
- modBaseAddr = NULL;
- modBaseSize = 0;
- for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++)
- rgProcAddresses[i] = LibcInfo::static_fn(i);
- }
- ModuleEntryCopy(const MODULEINFO& mi) {
- this->modBaseAddr = mi.lpBaseOfDll;
- this->modBaseSize = mi.SizeOfImage;
- LPVOID modEndAddr = (char*)mi.lpBaseOfDll + mi.SizeOfImage;
- for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) {
- FARPROC target = ::GetProcAddress(
- reinterpret_cast<const HMODULE>(mi.lpBaseOfDll),
- LibcInfo::function_name(i));
- // Sometimes a DLL forwards a function to a function in another
- // DLL. We don't want to patch those forwarded functions --
- // they'll get patched when the other DLL is processed.
- if (target >= modBaseAddr && target < modEndAddr)
- rgProcAddresses[i] = (GenericFnPtr)target;
- else
- rgProcAddresses[i] = (GenericFnPtr)NULL;
- }
- }
-};
-
-// This class is easier because there's only one of them.
-class WindowsInfo {
- public:
- void Patch();
- void Unpatch();
-
- private:
- // TODO(csilvers): should we be patching GlobalAlloc/LocalAlloc instead,
- // for pre-XP systems?
- enum {
- kHeapAlloc, kHeapFree, kVirtualAllocEx, kVirtualFreeEx,
- kMapViewOfFileEx, kUnmapViewOfFile, kLoadLibraryExW, kFreeLibrary,
- kNumFunctions
- };
-
- struct FunctionInfo {
- const char* const name; // name of fn in a module (eg "malloc")
- GenericFnPtr windows_fn; // the fn whose name we call (&malloc)
- GenericFnPtr origstub_fn; // original fn contents after we patch
- const GenericFnPtr perftools_fn; // fn we want to patch in
- };
-
- static FunctionInfo function_info_[kNumFunctions];
-
- // A Windows-API equivalent of malloc and free
- static LPVOID WINAPI Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
- DWORD_PTR dwBytes);
- static BOOL WINAPI Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
- LPVOID lpMem);
- // A Windows-API equivalent of mmap and munmap, for "anonymous regions"
- static LPVOID WINAPI Perftools_VirtualAllocEx(HANDLE process, LPVOID address,
- SIZE_T size, DWORD type,
- DWORD protect);
- static BOOL WINAPI Perftools_VirtualFreeEx(HANDLE process, LPVOID address,
- SIZE_T size, DWORD type);
- // A Windows-API equivalent of mmap and munmap, for actual files
- static LPVOID WINAPI Perftools_MapViewOfFileEx(HANDLE hFileMappingObject,
- DWORD dwDesiredAccess,
- DWORD dwFileOffsetHigh,
- DWORD dwFileOffsetLow,
- SIZE_T dwNumberOfBytesToMap,
- LPVOID lpBaseAddress);
- static BOOL WINAPI Perftools_UnmapViewOfFile(LPCVOID lpBaseAddress);
- // We don't need the other 3 variants because they all call this one. */
- static HMODULE WINAPI Perftools_LoadLibraryExW(LPCWSTR lpFileName,
- HANDLE hFile,
- DWORD dwFlags);
- static BOOL WINAPI Perftools_FreeLibrary(HMODULE hLibModule);
-};
-
-// If you run out, just add a few more to the array. You'll also need
-// to update the switch statement in PatchOneModule(), and the list in
-// UnpatchWindowsFunctions().
-// main_executable and main_executable_windows are two windows into
-// the same executable. One is responsible for patching the libc
-// routines that live in the main executable (if any) to use tcmalloc;
-// the other is responsible for patching the windows routines like
-// HeapAlloc/etc to use tcmalloc.
-static LibcInfoWithPatchFunctions<0> main_executable;
-static LibcInfoWithPatchFunctions<1> libc1;
-static LibcInfoWithPatchFunctions<2> libc2;
-static LibcInfoWithPatchFunctions<3> libc3;
-static LibcInfoWithPatchFunctions<4> libc4;
-static LibcInfoWithPatchFunctions<5> libc5;
-static LibcInfoWithPatchFunctions<6> libc6;
-static LibcInfoWithPatchFunctions<7> libc7;
-static LibcInfoWithPatchFunctions<8> libc8;
-static LibcInfo* g_module_libcs[] = {
- &libc1, &libc2, &libc3, &libc4, &libc5, &libc6, &libc7, &libc8
-};
-static WindowsInfo main_executable_windows;
-
-const char* const LibcInfo::function_name_[] = {
- "malloc", "free", "realloc", "calloc",
- kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray,
- // Ideally we should patch the nothrow versions of new/delete, but
- // at least in msvcrt, nothrow-new machine-code is of a type we
- // can't patch. Since these are relatively rare, I'm hoping it's ok
- // not to patch them. (NULL name turns off patching.)
- NULL, // kMangledNewNothrow,
- NULL, // kMangledNewArrayNothrow,
- NULL, // kMangledDeleteNothrow,
- NULL, // kMangledDeleteArrayNothrow,
- "_msize", "_expand", "_calloc_crt",
-};
-
-// For mingw, I can't patch the new/delete here, because the
-// instructions are too small to patch. Luckily, they're so small
-// because all they do is call into malloc/free, so they still end up
-// calling tcmalloc routines, and we don't actually lose anything
-// (except maybe some stacktrace goodness) by not patching.
-const GenericFnPtr LibcInfo::static_fn_[] = {
- (GenericFnPtr)&::malloc,
- (GenericFnPtr)&::free,
- (GenericFnPtr)&::realloc,
- (GenericFnPtr)&::calloc,
-#ifdef __MINGW32__
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-#else
- (GenericFnPtr)(void*(*)(size_t))&::operator new,
- (GenericFnPtr)(void*(*)(size_t))&::operator new[],
- (GenericFnPtr)(void(*)(void*))&::operator delete,
- (GenericFnPtr)(void(*)(void*))&::operator delete[],
- (GenericFnPtr)
- (void*(*)(size_t, struct std::nothrow_t const &))&::operator new,
- (GenericFnPtr)
- (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[],
- (GenericFnPtr)
- (void(*)(void*, struct std::nothrow_t const &))&::operator delete,
- (GenericFnPtr)
- (void(*)(void*, struct std::nothrow_t const &))&::operator delete[],
-#endif
- (GenericFnPtr)&::_msize,
- (GenericFnPtr)&::_expand,
- (GenericFnPtr)&::calloc,
-};
-
-template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = {
- // This will get filled in at run-time, as patching is done.
-};
-
-template<int T>
-const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = {
- (GenericFnPtr)&Perftools_malloc,
- (GenericFnPtr)&Perftools_free,
- (GenericFnPtr)&Perftools_realloc,
- (GenericFnPtr)&Perftools_calloc,
- (GenericFnPtr)&Perftools_new,
- (GenericFnPtr)&Perftools_newarray,
- (GenericFnPtr)&Perftools_delete,
- (GenericFnPtr)&Perftools_deletearray,
- (GenericFnPtr)&Perftools_new_nothrow,
- (GenericFnPtr)&Perftools_newarray_nothrow,
- (GenericFnPtr)&Perftools_delete_nothrow,
- (GenericFnPtr)&Perftools_deletearray_nothrow,
- (GenericFnPtr)&Perftools__msize,
- (GenericFnPtr)&Perftools__expand,
- (GenericFnPtr)&Perftools_calloc,
-};
-
-/*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = {
- { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc },
- { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree },
- { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx },
- { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx },
- { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx },
- { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile },
- { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW },
- { "FreeLibrary", NULL, NULL, (GenericFnPtr)&Perftools_FreeLibrary },
-};
-
-bool LibcInfo::PopulateWindowsFn(const ModuleEntryCopy& module_entry) {
- // First, store the location of the function to patch before
- // patching it. If none of these functions are found in the module,
- // then this module has no libc in it, and we just return false.
- for (int i = 0; i < kNumFunctions; i++) {
- if (!function_name_[i]) // we can turn off patching by unsetting name
- continue;
- // The ::GetProcAddress calls were done in the ModuleEntryCopy
- // constructor, so we don't have to make any windows calls here.
- const GenericFnPtr fn = module_entry.rgProcAddresses[i];
- if (fn) {
- windows_fn_[i] = PreamblePatcher::ResolveTarget(fn);
- }
- }
-
- // Some modules use the same function pointer for new and new[]. If
- // we find that, set one of the pointers to NULL so we don't double-
- // patch. Same may happen with new and nothrow-new, or even new[]
- // and nothrow-new. It's easiest just to check each fn-ptr against
- // every other.
- for (int i = 0; i < kNumFunctions; i++) {
- for (int j = i+1; j < kNumFunctions; j++) {
- if (windows_fn_[i] == windows_fn_[j]) {
- // We NULL the later one (j), so as to minimize the chances we
- // NULL kFree and kRealloc. See comments below. This is fragile!
- windows_fn_[j] = NULL;
- }
- }
- }
-
- // There's always a chance that our module uses the same function
- // as another module that we've already loaded. In that case, we
- // need to set our windows_fn to NULL, to avoid double-patching.
- for (int ifn = 0; ifn < kNumFunctions; ifn++) {
- for (int imod = 0;
- imod < sizeof(g_module_libcs)/sizeof(*g_module_libcs); imod++) {
- if (g_module_libcs[imod]->is_valid() &&
- this->windows_fn(ifn) == g_module_libcs[imod]->windows_fn(ifn)) {
- windows_fn_[ifn] = NULL;
- }
- }
- }
-
- bool found_non_null = false;
- for (int i = 0; i < kNumFunctions; i++) {
- if (windows_fn_[i])
- found_non_null = true;
- }
- if (!found_non_null)
- return false;
-
- // It's important we didn't NULL out windows_fn_[kFree] or [kRealloc].
- // The reason is, if those are NULL-ed out, we'll never patch them
- // and thus never get an origstub_fn_ value for them, and when we
- // try to call origstub_fn_[kFree/kRealloc] in Perftools_free and
- // Perftools_realloc, below, it will fail. We could work around
- // that by adding a pointer from one patch-unit to the other, but we
- // haven't needed to yet.
- CHECK(windows_fn_[kFree]);
- CHECK(windows_fn_[kRealloc]);
-
- // OK, we successfully populated. Let's store our member information.
- module_base_address_ = module_entry.modBaseAddr;
- module_base_size_ = module_entry.modBaseSize;
- return true;
-}
-
-template<int T>
-bool LibcInfoWithPatchFunctions<T>::Patch(const LibcInfo& me_info) {
- CopyFrom(me_info); // copies the module_entry and the windows_fn_ array
- for (int i = 0; i < kNumFunctions; i++) {
- if (windows_fn_[i] && windows_fn_[i] != perftools_fn_[i]) {
- // if origstub_fn_ is not NULL, it's left around from a previous
- // patch. We need to set it to NULL for the new Patch call.
- //
- // Note that origstub_fn_ was logically freed by
- // PreamblePatcher::Unpatch, so we don't have to do anything
- // about it.
- origstub_fn_[i] = NULL; // Patch() will fill this in
- CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
- PreamblePatcher::Patch(windows_fn_[i], perftools_fn_[i],
- &origstub_fn_[i]));
- }
- }
- set_is_valid(true);
- return true;
-}
-
-template<int T>
-void LibcInfoWithPatchFunctions<T>::Unpatch() {
- // We have to cast our GenericFnPtrs to void* for unpatch. This is
- // contra the C++ spec; we use C-style casts to empahsize that.
- for (int i = 0; i < kNumFunctions; i++) {
- if (windows_fn_[i])
- CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
- PreamblePatcher::Unpatch((void*)windows_fn_[i],
- (void*)perftools_fn_[i],
- (void*)origstub_fn_[i]));
- }
- set_is_valid(false);
-}
-
-void WindowsInfo::Patch() {
- HMODULE hkernel32 = ::GetModuleHandleA("kernel32");
- CHECK_NE(hkernel32, NULL);
-
- // Unlike for libc, we know these exist in our module, so we can get
- // and patch at the same time.
- for (int i = 0; i < kNumFunctions; i++) {
- function_info_[i].windows_fn = (GenericFnPtr)
- ::GetProcAddress(hkernel32, function_info_[i].name);
- // If origstub_fn is not NULL, it's left around from a previous
- // patch. We need to set it to NULL for the new Patch call.
- // Since we've patched Unpatch() not to delete origstub_fn_ (it
- // causes problems in some contexts, though obviously not this
- // one), we should delete it now, before setting it to NULL.
- // NOTE: casting from a function to a pointer is contra the C++
- // spec. It's not safe on IA64, but is on i386. We use
- // a C-style cast here to emphasize this is not legal C++.
- delete[] (char*)(function_info_[i].origstub_fn);
- function_info_[i].origstub_fn = NULL; // Patch() will fill this in
- CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
- PreamblePatcher::Patch(function_info_[i].windows_fn,
- function_info_[i].perftools_fn,
- &function_info_[i].origstub_fn));
- }
-}
-
-void WindowsInfo::Unpatch() {
- // We have to cast our GenericFnPtrs to void* for unpatch. This is
- // contra the C++ spec; we use C-style casts to empahsize that.
- for (int i = 0; i < kNumFunctions; i++) {
- CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
- PreamblePatcher::Unpatch((void*)function_info_[i].windows_fn,
- (void*)function_info_[i].perftools_fn,
- (void*)function_info_[i].origstub_fn));
- }
-}
-
-// You should hold the patch_all_modules_lock when calling this.
-void PatchOneModuleLocked(const LibcInfo& me_info) {
- // If we don't already have info on this module, let's add it. This
- // is where we're sad that each libcX has a different type, so we
- // can't use an array; instead, we have to use a switch statement.
- // Patch() returns false if there were no libc functions in the module.
- for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) {
- if (!g_module_libcs[i]->is_valid()) { // found an empty spot to add!
- switch (i) {
- case 0: libc1.Patch(me_info); return;
- case 1: libc2.Patch(me_info); return;
- case 2: libc3.Patch(me_info); return;
- case 3: libc4.Patch(me_info); return;
- case 4: libc5.Patch(me_info); return;
- case 5: libc6.Patch(me_info); return;
- case 6: libc7.Patch(me_info); return;
- case 7: libc8.Patch(me_info); return;
- }
- }
- }
- printf("PERFTOOLS ERROR: Too many modules containing libc in this executable\n");
-}
-
-void PatchMainExecutableLocked() {
- if (main_executable.patched())
- return; // main executable has already been patched
- ModuleEntryCopy fake_module_entry; // make a fake one to pass into Patch()
- // No need to call PopulateModuleEntryProcAddresses on the main executable.
- main_executable.PopulateWindowsFn(fake_module_entry);
- main_executable.Patch(main_executable);
-}
-
-// This lock is subject to a subtle and annoying lock inversion
-// problem: it may interact badly with unknown internal windows locks.
-// In particular, windows may be holding a lock when it calls
-// LoadLibraryExW and FreeLibrary, which we've patched. We have those
-// routines call PatchAllModules, which acquires this lock. If we
-// make windows system calls while holding this lock, those system
-// calls may need the internal windows locks that are being held in
-// the call to LoadLibraryExW, resulting in deadlock. The solution is
-// to be very careful not to call *any* windows routines while holding
-// patch_all_modules_lock, inside PatchAllModules().
-static SpinLock patch_all_modules_lock(SpinLock::LINKER_INITIALIZED);
-
-// last_loaded: The set of modules that were loaded the last time
-// PatchAllModules was called. This is an optimization for only
-// looking at modules that were added or removed from the last call.
-static std::set<HMODULE> *g_last_loaded;
-
-// Iterates over all the modules currently loaded by the executable,
-// according to windows, and makes sure they're all patched. Most
-// modules will already be in loaded_modules, meaning we have already
-// loaded and either patched them or determined they did not need to
-// be patched. Others will not, which means we need to patch them
-// (if necessary). Finally, we have to go through the existing
-// g_module_libcs and see if any of those are *not* in the modules
-// currently loaded by the executable. If so, we need to invalidate
-// them. Returns true if we did any work (patching or invalidating),
-// false if we were a noop. May update loaded_modules as well.
-// NOTE: you must hold the patch_all_modules_lock to access loaded_modules.
-bool PatchAllModules() {
- std::vector<ModuleEntryCopy> modules;
- bool made_changes = false;
-
- const HANDLE hCurrentProcess = GetCurrentProcess();
- DWORD num_modules = 0;
- HMODULE hModules[kMaxModules]; // max # of modules we support in one process
- if (!::EnumProcessModules(hCurrentProcess, hModules, sizeof(hModules),
- &num_modules)) {
- num_modules = 0;
- }
- // EnumProcessModules actually set the bytes written into hModules,
- // so we need to divide to make num_modules actually be a module-count.
- num_modules /= sizeof(*hModules);
- if (num_modules >= kMaxModules) {
- printf("PERFTOOLS ERROR: Too many modules in this executable to try"
- " to patch them all (if you need to, raise kMaxModules in"
- " patch_functions.cc).\n");
- num_modules = kMaxModules;
- }
-
- // Now we handle the unpatching of modules we have in g_module_libcs
- // but that were not found in EnumProcessModules. We need to
- // invalidate them. To speed that up, we store the EnumProcessModules
- // output in a set.
- // At the same time, we prepare for the adding of new modules, by
- // removing from hModules all the modules we know we've already
- // patched (or decided don't need to be patched). At the end,
- // hModules will hold only the modules that we need to consider patching.
- std::set<HMODULE> currently_loaded_modules;
- {
- SpinLockHolder h(&patch_all_modules_lock);
- if (!g_last_loaded) g_last_loaded = new std::set<HMODULE>;
- // At the end of this loop, currently_loaded_modules contains the
- // full list of EnumProcessModules, and hModules just the ones we
- // haven't handled yet.
- for (int i = 0; i < num_modules; ) {
- currently_loaded_modules.insert(hModules[i]);
- if (g_last_loaded->count(hModules[i]) > 0) {
- hModules[i] = hModules[--num_modules]; // replace element i with tail
- } else {
- i++; // keep element i
- }
- }
- // Now we do the unpatching/invalidation.
- for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) {
- if (g_module_libcs[i]->patched() &&
- currently_loaded_modules.count(g_module_libcs[i]->hmodule()) == 0) {
- // Means g_module_libcs[i] is no longer loaded (no me32 matched).
- // We could call Unpatch() here, but why bother? The module
- // has gone away, so nobody is going to call into it anyway.
- g_module_libcs[i]->set_is_valid(false);
- made_changes = true;
- }
- }
- // Update the loaded module cache.
- g_last_loaded->swap(currently_loaded_modules);
- }
-
- // Now that we know what modules are new, let's get the info we'll
- // need to patch them. Note this *cannot* be done while holding the
- // lock, since it needs to make windows calls (see the lock-inversion
- // comments before the definition of patch_all_modules_lock).
- MODULEINFO mi;
- for (int i = 0; i < num_modules; i++) {
- if (::GetModuleInformation(hCurrentProcess, hModules[i], &mi, sizeof(mi)))
- modules.push_back(ModuleEntryCopy(mi));
- }
-
- // Now we can do the patching of new modules.
- {
- SpinLockHolder h(&patch_all_modules_lock);
- for (std::vector<ModuleEntryCopy>::iterator it = modules.begin();
- it != modules.end(); ++it) {
- LibcInfo libc_info;
- if (libc_info.PopulateWindowsFn(*it)) { // true==module has libc routines
- PatchOneModuleLocked(libc_info);
- made_changes = true;
- }
- }
-
- // Now that we've dealt with the modules (dlls), update the main
- // executable. We do this last because PatchMainExecutableLocked
- // wants to look at how other modules were patched.
- if (!main_executable.patched()) {
- PatchMainExecutableLocked();
- made_changes = true;
- }
- }
- // TODO(csilvers): for this to be reliable, we need to also take
- // into account if we *would* have patched any modules had they not
- // already been loaded. (That is, made_changes should ignore
- // g_last_loaded.)
- return made_changes;
-}
-
-
-} // end unnamed namespace
-
-// ---------------------------------------------------------------------
-// Now that we've done all the patching machinery, let's actually
-// define the functions we're patching in. Mostly these are
-// simple wrappers around the do_* routines in tcmalloc.cc.
-//
-// In fact, we #include tcmalloc.cc to get at the tcmalloc internal
-// do_* functions, the better to write our own hook functions.
-// U-G-L-Y, I know. But the alternatives are, perhaps, worse. This
-// also lets us define _msize(), _expand(), and other windows-specific
-// functions here, using tcmalloc internals, without polluting
-// tcmalloc.cc.
-// -------------------------------------------------------------------
-
-// TODO(csilvers): refactor tcmalloc.cc into two files, so I can link
-// against the file with do_malloc, and ignore the one with malloc.
-#include "tcmalloc.cc"
-
-template<int T>
-void* LibcInfoWithPatchFunctions<T>::Perftools_malloc(size_t size) __THROW {
- void* result = do_malloc_or_cpp_alloc(size);
- MallocHook::InvokeNewHook(result, size);
- return result;
-}
-
-template<int T>
-void LibcInfoWithPatchFunctions<T>::Perftools_free(void* ptr) __THROW {
- MallocHook::InvokeDeleteHook(ptr);
- // This calls the windows free if do_free decides ptr was not
- // allocated by tcmalloc. Note it calls the origstub_free from
- // *this* templatized instance of LibcInfo. See "template
- // trickiness" above.
- do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[kFree], false, 0);
-}
-
-template<int T>
-void* LibcInfoWithPatchFunctions<T>::Perftools_realloc(
- void* old_ptr, size_t new_size) __THROW {
- if (old_ptr == NULL) {
- void* result = do_malloc_or_cpp_alloc(new_size);
- MallocHook::InvokeNewHook(result, new_size);
- return result;
- }
- if (new_size == 0) {
- MallocHook::InvokeDeleteHook(old_ptr);
- do_free_with_callback(old_ptr,
- (void (*)(void*))origstub_fn_[kFree], false, 0);
- return NULL;
- }
- return do_realloc_with_callback(
- old_ptr, new_size,
- (void (*)(void*))origstub_fn_[kFree],
- (size_t (*)(const void*))origstub_fn_[k_Msize]);
-}
-
-template<int T>
-void* LibcInfoWithPatchFunctions<T>::Perftools_calloc(
- size_t n, size_t elem_size) __THROW {
- void* result = do_calloc(n, elem_size);
- MallocHook::InvokeNewHook(result, n * elem_size);
- return result;
-}
-
-template<int T>
-void* LibcInfoWithPatchFunctions<T>::Perftools_new(size_t size) {
- void* p = cpp_alloc(size, false);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-template<int T>
-void* LibcInfoWithPatchFunctions<T>::Perftools_newarray(size_t size) {
- void* p = cpp_alloc(size, false);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-template<int T>
-void LibcInfoWithPatchFunctions<T>::Perftools_delete(void *p) {
- MallocHook::InvokeDeleteHook(p);
- do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0);
-}
-
-template<int T>
-void LibcInfoWithPatchFunctions<T>::Perftools_deletearray(void *p) {
- MallocHook::InvokeDeleteHook(p);
- do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0);
-}
-
-template<int T>
-void* LibcInfoWithPatchFunctions<T>::Perftools_new_nothrow(
- size_t size, const std::nothrow_t&) __THROW {
- void* p = cpp_alloc(size, true);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-template<int T>
-void* LibcInfoWithPatchFunctions<T>::Perftools_newarray_nothrow(
- size_t size, const std::nothrow_t&) __THROW {
- void* p = cpp_alloc(size, true);
- MallocHook::InvokeNewHook(p, size);
- return p;
-}
-
-template<int T>
-void LibcInfoWithPatchFunctions<T>::Perftools_delete_nothrow(
- void *p, const std::nothrow_t&) __THROW {
- MallocHook::InvokeDeleteHook(p);
- do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0);
-}
-
-template<int T>
-void LibcInfoWithPatchFunctions<T>::Perftools_deletearray_nothrow(
- void *p, const std::nothrow_t&) __THROW {
- MallocHook::InvokeDeleteHook(p);
- do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0);
-}
-
-
-// _msize() lets you figure out how much space is reserved for a
-// pointer, in Windows. Even if applications don't call it, any DLL
-// with global constructors will call (transitively) something called
-// __dllonexit_lk in order to make sure the destructors get called
-// when the dll unloads. And that will call msize -- horrible things
-// can ensue if this is not hooked. Other parts of libc may also call
-// this internally.
-
-template<int T>
-size_t LibcInfoWithPatchFunctions<T>::Perftools__msize(void* ptr) __THROW {
- return GetSizeWithCallback(ptr, (size_t (*)(const void*))origstub_fn_[k_Msize]);
-}
-
-// We need to define this because internal windows functions like to
-// call into it(?). _expand() is like realloc but doesn't move the
-// pointer. We punt, which will cause callers to fall back on realloc.
-template<int T>
-void* LibcInfoWithPatchFunctions<T>::Perftools__expand(void *ptr,
- size_t size) __THROW {
- return NULL;
-}
-
-LPVOID WINAPI WindowsInfo::Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
- DWORD_PTR dwBytes) {
- LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD_PTR))
- function_info_[kHeapAlloc].origstub_fn)(
- hHeap, dwFlags, dwBytes);
- MallocHook::InvokeNewHook(result, dwBytes);
- return result;
-}
-
-BOOL WINAPI WindowsInfo::Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
- LPVOID lpMem) {
- MallocHook::InvokeDeleteHook(lpMem);
- return ((BOOL (WINAPI *)(HANDLE, DWORD, LPVOID))
- function_info_[kHeapFree].origstub_fn)(
- hHeap, dwFlags, lpMem);
-}
-
-LPVOID WINAPI WindowsInfo::Perftools_VirtualAllocEx(HANDLE process,
- LPVOID address,
- SIZE_T size, DWORD type,
- DWORD protect) {
- LPVOID result = ((LPVOID (WINAPI *)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD))
- function_info_[kVirtualAllocEx].origstub_fn)(
- process, address, size, type, protect);
- // VirtualAllocEx() seems to be the Windows equivalent of mmap()
- MallocHook::InvokeMmapHook(result, address, size, protect, type, -1, 0);
- return result;
-}
-
-BOOL WINAPI WindowsInfo::Perftools_VirtualFreeEx(HANDLE process, LPVOID address,
- SIZE_T size, DWORD type) {
- MallocHook::InvokeMunmapHook(address, size);
- return ((BOOL (WINAPI *)(HANDLE, LPVOID, SIZE_T, DWORD))
- function_info_[kVirtualFreeEx].origstub_fn)(
- process, address, size, type);
-}
-
-LPVOID WINAPI WindowsInfo::Perftools_MapViewOfFileEx(
- HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
- DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) {
- // For this function pair, you always deallocate the full block of
- // data that you allocate, so NewHook/DeleteHook is the right API.
- LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD, DWORD,
- SIZE_T, LPVOID))
- function_info_[kMapViewOfFileEx].origstub_fn)(
- hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
- dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress);
- MallocHook::InvokeNewHook(result, dwNumberOfBytesToMap);
- return result;
-}
-
-BOOL WINAPI WindowsInfo::Perftools_UnmapViewOfFile(LPCVOID lpBaseAddress) {
- MallocHook::InvokeDeleteHook(lpBaseAddress);
- return ((BOOL (WINAPI *)(LPCVOID))
- function_info_[kUnmapViewOfFile].origstub_fn)(
- lpBaseAddress);
-}
-
-// g_load_map holds a copy of windows' refcount for how many times
-// each currently loaded module has been loaded and unloaded. We use
-// it as an optimization when the same module is loaded more than
-// once: as long as the refcount stays above 1, we don't need to worry
-// about patching because it's already patched. Likewise, we don't
-// need to unpatch until the refcount drops to 0. load_map is
-// maintained in LoadLibraryExW and FreeLibrary, and only covers
-// modules explicitly loaded/freed via those interfaces.
-static std::map<HMODULE, int>* g_load_map = NULL;
-
-HMODULE WINAPI WindowsInfo::Perftools_LoadLibraryExW(LPCWSTR lpFileName,
- HANDLE hFile,
- DWORD dwFlags) {
- HMODULE rv;
- // Check to see if the modules is already loaded, flag 0 gets a
- // reference if it was loaded. If it was loaded no need to call
- // PatchAllModules, just increase the reference count to match
- // what GetModuleHandleExW does internally inside windows.
- if (::GetModuleHandleExW(0, lpFileName, &rv)) {
- return rv;
- } else {
- // Not already loaded, so load it.
- rv = ((HMODULE (WINAPI *)(LPCWSTR, HANDLE, DWORD))
- function_info_[kLoadLibraryExW].origstub_fn)(
- lpFileName, hFile, dwFlags);
- // This will patch any newly loaded libraries, if patching needs
- // to be done.
- PatchAllModules();
-
- return rv;
- }
-}
-
-BOOL WINAPI WindowsInfo::Perftools_FreeLibrary(HMODULE hLibModule) {
- BOOL rv = ((BOOL (WINAPI *)(HMODULE))
- function_info_[kFreeLibrary].origstub_fn)(hLibModule);
-
- // Check to see if the module is still loaded by passing the base
- // address and seeing if it comes back with the same address. If it
- // is the same address it's still loaded, so the FreeLibrary() call
- // was a noop, and there's no need to redo the patching.
- HMODULE owner = NULL;
- BOOL result = ::GetModuleHandleExW(
- (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
- GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
- (LPCWSTR)hLibModule,
- &owner);
- if (result && owner == hLibModule)
- return rv;
-
- PatchAllModules(); // this will fix up the list of patched libraries
- return rv;
-}
-
-
-// ---------------------------------------------------------------------
-// PatchWindowsFunctions()
-// This is the function that is exposed to the outside world.
-// It should be called before the program becomes multi-threaded,
-// since main_executable_windows.Patch() is not thread-safe.
-// ---------------------------------------------------------------------
-
-void PatchWindowsFunctions() {
- // This does the libc patching in every module, and the main executable.
- PatchAllModules();
- main_executable_windows.Patch();
-}
-
-#if 0
-// It's possible to unpatch all the functions when we are exiting.
-
-// The idea is to handle properly windows-internal data that is
-// allocated before PatchWindowsFunctions is called. If all
-// destruction happened in reverse order from construction, then we
-// could call UnpatchWindowsFunctions at just the right time, so that
-// that early-allocated data would be freed using the windows
-// allocation functions rather than tcmalloc. The problem is that
-// windows allocates some structures lazily, so it would allocate them
-// late (using tcmalloc) and then try to deallocate them late as well.
-// So instead of unpatching, we just modify all the tcmalloc routines
-// so they call through to the libc rountines if the memory in
-// question doesn't seem to have been allocated with tcmalloc. I keep
-// this unpatch code around for reference.
-
-void UnpatchWindowsFunctions() {
- // We need to go back to the system malloc/etc at global destruct time,
- // so objects that were constructed before tcmalloc, using the system
- // malloc, can destroy themselves using the system free. This depends
- // on DLLs unloading in the reverse order in which they load!
- //
- // We also go back to the default HeapAlloc/etc, just for consistency.
- // Who knows, it may help avoid weird bugs in some situations.
- main_executable_windows.Unpatch();
- main_executable.Unpatch();
- if (libc1.is_valid()) libc1.Unpatch();
- if (libc2.is_valid()) libc2.Unpatch();
- if (libc3.is_valid()) libc3.Unpatch();
- if (libc4.is_valid()) libc4.Unpatch();
- if (libc5.is_valid()) libc5.Unpatch();
- if (libc6.is_valid()) libc6.Unpatch();
- if (libc7.is_valid()) libc7.Unpatch();
- if (libc8.is_valid()) libc8.Unpatch();
-}
-#endif
diff --git a/src/third_party/gperftools-2.5/src/windows/port.cc b/src/third_party/gperftools-2.5/src/windows/port.cc
deleted file mode 100644
index a8dd1d91af7..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/port.cc
+++ /dev/null
@@ -1,249 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2007, 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
- */
-
-#ifndef _WIN32
-# error You should only be including windows/port.cc in a windows environment!
-#endif
-
-#define NOMINMAX // so std::max, below, compiles correctly
-#include <config.h>
-#include <string.h> // for strlen(), memset(), memcmp()
-#include <assert.h>
-#include <stdarg.h> // for va_list, va_start, va_end
-#include <algorithm> // for std:{min,max}
-#include <windows.h>
-#include "port.h"
-#include "base/logging.h"
-#include "base/spinlock.h"
-#include "internal_logging.h"
-
-// -----------------------------------------------------------------------
-// Basic libraries
-
-PERFTOOLS_DLL_DECL
-int getpagesize() {
- static int pagesize = 0;
- if (pagesize == 0) {
- SYSTEM_INFO system_info;
- GetSystemInfo(&system_info);
- pagesize = std::max(system_info.dwPageSize,
- system_info.dwAllocationGranularity);
- }
- return pagesize;
-}
-
-extern "C" PERFTOOLS_DLL_DECL void* __sbrk(ptrdiff_t increment) {
- LOG(FATAL, "Windows doesn't implement sbrk!\n");
- return NULL;
-}
-
-// We need to write to 'stderr' without having windows allocate memory.
-// The safest way is via a low-level call like WriteConsoleA(). But
-// even then we need to be sure to print in small bursts so as to not
-// require memory allocation.
-extern "C" PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len) {
- // Looks like windows allocates for writes of >80 bytes
- for (int i = 0; i < len; i += 80) {
- write(STDERR_FILENO, buf + i, std::min(80, len - i));
- }
-}
-
-
-// -----------------------------------------------------------------------
-// Threads code
-
-// Windows doesn't support pthread_key_create's destr_function, and in
-// fact it's a bit tricky to get code to run when a thread exits. This
-// is cargo-cult magic from https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
-// and http://lallouslab.net/2017/05/30/using-cc-tls-callbacks-in-visual-studio-with-your-32-or-64bits-programs/.
-// This code is for VC++ 7.1 and later; VC++ 6.0 support is possible
-// but more busy-work -- see the webpage for how to do it. If all
-// this fails, we could use DllMain instead. The big problem with
-// DllMain is it doesn't run if this code is statically linked into a
-// binary (it also doesn't run if the thread is terminated via
-// TerminateThread, which if we're lucky this routine does).
-
-// Force a reference to _tls_used to make the linker create the TLS directory
-// if it's not already there (that is, even if __declspec(thread) is not used).
-// Force a reference to p_thread_callback_tcmalloc and p_process_term_tcmalloc
-// to prevent whole program optimization from discarding the variables.
-#ifdef _MSC_VER
-#if defined(_M_IX86)
-#pragma comment(linker, "/INCLUDE:__tls_used")
-#pragma comment(linker, "/INCLUDE:_p_thread_callback_tcmalloc")
-#pragma comment(linker, "/INCLUDE:_p_process_term_tcmalloc")
-#elif defined(_M_X64)
-#pragma comment(linker, "/INCLUDE:_tls_used")
-#pragma comment(linker, "/INCLUDE:p_thread_callback_tcmalloc")
-#pragma comment(linker, "/INCLUDE:p_process_term_tcmalloc")
-#endif
-#endif
-
-// When destr_fn eventually runs, it's supposed to take as its
-// argument the tls-value associated with key that pthread_key_create
-// creates. (Yeah, it sounds confusing but it's really not.) We
-// store the destr_fn/key pair in this data structure. Because we
-// store this in a single var, this implies we can only have one
-// destr_fn in a program! That's enough in practice. If asserts
-// trigger because we end up needing more, we'll have to turn this
-// into an array.
-struct DestrFnClosure {
- void (*destr_fn)(void*);
- pthread_key_t key_for_destr_fn_arg;
-};
-
-static DestrFnClosure destr_fn_info; // initted to all NULL/0.
-
-static int on_process_term(void) {
- if (destr_fn_info.destr_fn) {
- void *ptr = TlsGetValue(destr_fn_info.key_for_destr_fn_arg);
- // This shouldn't be necessary, but in Release mode, Windows
- // sometimes trashes the pointer in the TLS slot, so we need to
- // remove the pointer from the TLS slot before the thread dies.
- TlsSetValue(destr_fn_info.key_for_destr_fn_arg, NULL);
- if (ptr) // pthread semantics say not to call if ptr is NULL
- (*destr_fn_info.destr_fn)(ptr);
- }
- return 0;
-}
-
-static void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv) {
- if (dwReason == DLL_THREAD_DETACH) { // thread is being destroyed!
- on_process_term();
- }
-}
-
-#ifdef _MSC_VER
-
-// extern "C" suppresses C++ name mangling so we know the symbol names
-// for the linker /INCLUDE:symbol pragmas above.
-// Note that for some unknown reason, the extern "C" {} construct is ignored
-// by the MSVC VS2017 compiler (at least) when a const modifier is used
-#if defined(_M_IX86)
-extern "C" {
-// In x86, the PE loader looks for callbacks in a data segment
-#pragma data_seg(push, old_seg)
-#pragma data_seg(".CRT$XLB")
-void (NTAPI *p_thread_callback_tcmalloc)(
- HINSTANCE h, DWORD dwReason, PVOID pv) = on_tls_callback;
-#pragma data_seg(".CRT$XTU")
-int (*p_process_term_tcmalloc)(void) = on_process_term;
-#pragma data_seg(pop, old_seg)
-} // extern "C"
-#elif defined(_M_X64)
-// In x64, the PE loader looks for callbacks in a constant segment
-#pragma const_seg(push, oldseg)
-#pragma const_seg(".CRT$XLB")
-extern "C" void (NTAPI * const p_thread_callback_tcmalloc)(
- HINSTANCE h, DWORD dwReason, PVOID pv) = on_tls_callback;
-#pragma const_seg(".CRT$XTU")
-extern "C" int (NTAPI * const p_process_term_tcmalloc)(void) = on_process_term;
-#pragma const_seg(pop, oldseg)
-#endif
-
-#else // #ifdef _MSC_VER [probably msys/mingw]
-
-// We have to try the DllMain solution here, because we can't use the
-// msvc-specific pragmas.
-BOOL WINAPI DllMain(HINSTANCE h, DWORD dwReason, PVOID pv) {
- if (dwReason == DLL_THREAD_DETACH)
- on_tls_callback(h, dwReason, pv);
- else if (dwReason == DLL_PROCESS_DETACH)
- on_process_term();
- return TRUE;
-}
-
-#endif // #ifdef _MSC_VER
-
-extern "C" pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)) {
- // Semantics are: we create a new key, and then promise to call
- // destr_fn with TlsGetValue(key) when the thread is destroyed
- // (as long as TlsGetValue(key) is not NULL).
- pthread_key_t key = TlsAlloc();
- if (destr_fn) { // register it
- // If this assert fails, we'll need to support an array of destr_fn_infos
- assert(destr_fn_info.destr_fn == NULL);
- destr_fn_info.destr_fn = destr_fn;
- destr_fn_info.key_for_destr_fn_arg = key;
- }
- return key;
-}
-
-// NOTE: this is Win2K and later. For Win98 we could use a CRITICAL_SECTION...
-extern "C" int perftools_pthread_once(pthread_once_t *once_control,
- void (*init_routine)(void)) {
- // Try for a fast path first. Note: this should be an acquire semantics read.
- // It is on x86 and x64, where Windows runs.
- if (*once_control != 1) {
- while (true) {
- switch (InterlockedCompareExchange(once_control, 2, 0)) {
- case 0:
- init_routine();
- InterlockedExchange(once_control, 1);
- return 0;
- case 1:
- // The initializer has already been executed
- return 0;
- default:
- // The initializer is being processed by another thread
- SwitchToThread();
- }
- }
- }
- return 0;
-}
-
-
-// -----------------------------------------------------------------------
-// These functions rework existing functions of the same name in the
-// Google codebase.
-
-// A replacement for HeapProfiler::CleanupOldProfiles.
-void DeleteMatchingFiles(const char* prefix, const char* full_glob) {
- WIN32_FIND_DATAA found; // that final A is for Ansi (as opposed to Unicode)
- HANDLE hFind = FindFirstFileA(full_glob, &found); // A is for Ansi
- if (hFind != INVALID_HANDLE_VALUE) {
- const int prefix_length = strlen(prefix);
- do {
- const char *fname = found.cFileName;
- if ((strlen(fname) >= prefix_length) &&
- (memcmp(fname, prefix, prefix_length) == 0)) {
- RAW_VLOG(0, "Removing old heap profile %s\n", fname);
- // TODO(csilvers): we really need to unlink dirname + fname
- _unlink(fname);
- }
- } while (FindNextFileA(hFind, &found) != FALSE); // A is for Ansi
- FindClose(hFind);
- }
-}
diff --git a/src/third_party/gperftools-2.5/src/windows/port.h b/src/third_party/gperftools-2.5/src/windows/port.h
deleted file mode 100644
index 87db9ddc848..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/port.h
+++ /dev/null
@@ -1,497 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2007, 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
- *
- * These are some portability typedefs and defines to make it a bit
- * easier to compile this code under VC++.
- *
- * Several of these are taken from glib:
- * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
- */
-
-#ifndef GOOGLE_BASE_WINDOWS_H_
-#define GOOGLE_BASE_WINDOWS_H_
-
-/* You should never include this file directly, but always include it
- from either config.h (MSVC) or mingw.h (MinGW/msys). */
-#if !defined(GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_) && \
- !defined(GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_)
-# error "port.h should only be included from config.h or mingw.h"
-#endif
-
-#ifdef _WIN32
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
-#endif
-#include <windows.h>
-#include <io.h> /* because we so often use open/close/etc */
-#include <direct.h> /* for _getcwd */
-#include <process.h> /* for _getpid */
-#include <limits.h> /* for PATH_MAX */
-#include <stdarg.h> /* for va_list */
-#include <stdio.h> /* need this to override stdio's (v)snprintf */
-#include <sys/types.h> /* for _off_t */
-#include <assert.h>
-#include <stdlib.h> /* for rand, srand, _strtoxxx */
-
-#if defined(_MSC_VER) && _MSC_VER >= 1900
-#define _TIMESPEC_DEFINED
-#include <time.h>
-#endif
-
-/*
- * 4018: signed/unsigned mismatch is common (and ok for signed_i < unsigned_i)
- * 4244: otherwise we get problems when subtracting two size_t's to an int
- * 4288: VC++7 gets confused when a var is defined in a loop and then after it
- * 4267: too many false positives for "conversion gives possible data loss"
- * 4290: it's ok windows ignores the "throw" directive
- * 4996: Yes, we're ok using "unsafe" functions like vsnprintf and getenv()
- * 4146: internal_logging.cc intentionally negates an unsigned value
- */
-#ifdef _MSC_VER
-#pragma warning(disable:4018 4244 4288 4267 4290 4996 4146)
-#endif
-
-#ifndef __cplusplus
-/* MSVC does not support C99 */
-# if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
-# ifdef _MSC_VER
-# define inline __inline
-# else
-# define inline static
-# endif
-# endif
-#endif
-
-#ifdef __cplusplus
-# define EXTERN_C extern "C"
-#else
-# define EXTERN_C extern
-#endif
-
-/* ----------------------------------- BASIC TYPES */
-
-#ifndef HAVE_STDINT_H
-#ifndef HAVE___INT64 /* we need to have all the __intX names */
-# error Do not know how to set up type aliases. Edit port.h for your system.
-#endif
-
-typedef __int8 int8_t;
-typedef __int16 int16_t;
-typedef __int32 int32_t;
-typedef __int64 int64_t;
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int64 uint64_t;
-#endif /* #ifndef HAVE_STDINT_H */
-
-/* I guess MSVC's <types.h> doesn't include ssize_t by default? */
-#ifdef _MSC_VER
-typedef intptr_t ssize_t;
-#endif
-
-/* ----------------------------------- THREADS */
-
-#ifndef HAVE_PTHREAD /* not true for MSVC, but may be true for MSYS */
-typedef DWORD pthread_t;
-typedef DWORD pthread_key_t;
-typedef LONG pthread_once_t;
-enum { PTHREAD_ONCE_INIT = 0 }; /* important that this be 0! for SpinLock */
-
-inline pthread_t pthread_self(void) {
- return GetCurrentThreadId();
-}
-
-#ifdef __cplusplus
-inline bool pthread_equal(pthread_t left, pthread_t right) {
- return left == right;
-}
-
-/*
- * windows/port.h defines compatibility APIs for several .h files, which
- * we therefore shouldn't be #including directly. This hack keeps us from
- * doing so. TODO(csilvers): do something more principled.
- */
-#define GOOGLE_MAYBE_THREADS_H_ 1
-/* This replaces maybe_threads.{h,cc} */
-
-EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); /* port.cc */
-
-inline int perftools_pthread_key_create(pthread_key_t *pkey,
- void (*destructor)(void*)) {
- pthread_key_t key = PthreadKeyCreate(destructor);
- if (key != TLS_OUT_OF_INDEXES) {
- *(pkey) = key;
- return 0;
- } else {
- return GetLastError();
- }
-}
-
-inline void* perftools_pthread_getspecific(DWORD key) {
- DWORD err = GetLastError();
- void* rv = TlsGetValue(key);
- if (err) SetLastError(err);
- return rv;
-}
-
-inline int perftools_pthread_setspecific(pthread_key_t key, const void *value) {
- if (TlsSetValue(key, (LPVOID)value))
- return 0;
- else
- return GetLastError();
-}
-
-EXTERN_C int perftools_pthread_once(pthread_once_t *once_control,
- void (*init_routine)(void));
-
-#endif /* __cplusplus */
-
-inline void sched_yield(void) {
- Sleep(0);
-}
-
-#endif /* HAVE_PTHREAD */
-
-/*
- * __declspec(thread) isn't usable in a dll opened via LoadLibrary().
- * But it doesn't work to LoadLibrary() us anyway, because of all the
- * things we need to do before main()! So this kind of TLS is safe for us.
- */
-#define __thread __declspec(thread)
-
-/*
- * This code is obsolete, but I keep it around in case we are ever in
- * an environment where we can't or don't want to use google spinlocks
- * (from base/spinlock.{h,cc}). In that case, uncommenting this out,
- * and removing spinlock.cc from the build, should be enough to revert
- * back to using native spinlocks.
- */
-#if 0
-// Windows uses a spinlock internally for its mutexes, making our life easy!
-// However, the Windows spinlock must always be initialized, making life hard,
-// since we want LINKER_INITIALIZED. We work around this by having the
-// linker initialize a bool to 0, and check that before accessing the mutex.
-// This replaces spinlock.{h,cc}, and all the stuff it depends on (atomicops)
-#ifdef __cplusplus
-class SpinLock {
- public:
- SpinLock() : initialize_token_(PTHREAD_ONCE_INIT) {}
- // Used for global SpinLock vars (see base/spinlock.h for more details).
- enum StaticInitializer { LINKER_INITIALIZED };
- explicit SpinLock(StaticInitializer) : initialize_token_(PTHREAD_ONCE_INIT) {
- perftools_pthread_once(&initialize_token_, InitializeMutex);
- }
-
- // It's important SpinLock not have a destructor: otherwise we run
- // into problems when the main thread has exited, but other threads
- // are still running and try to access a main-thread spinlock. This
- // means we leak mutex_ (we should call DeleteCriticalSection()
- // here). However, I've verified that all SpinLocks used in
- // perftools have program-long scope anyway, so the leak is
- // perfectly fine. But be aware of this for the future!
-
- void Lock() {
- // You'd thionk this would be unnecessary, since we call
- // InitializeMutex() in our constructor. But sometimes Lock() can
- // be called before our constructor is! This can only happen in
- // global constructors, when this is a global. If we live in
- // bar.cc, and some global constructor in foo.cc calls a routine
- // in bar.cc that calls this->Lock(), then Lock() may well run
- // before our global constructor does. To protect against that,
- // we do this check. For SpinLock objects created after main()
- // has started, this pthread_once call will always be a noop.
- perftools_pthread_once(&initialize_token_, InitializeMutex);
- EnterCriticalSection(&mutex_);
- }
- void Unlock() {
- LeaveCriticalSection(&mutex_);
- }
-
- // Used in assertion checks: assert(lock.IsHeld()) (see base/spinlock.h).
- inline bool IsHeld() const {
- // This works, but probes undocumented internals, so I've commented it out.
- // c.f. http://msdn.microsoft.com/msdnmag/issues/03/12/CriticalSections/
- //return mutex_.LockCount>=0 && mutex_.OwningThread==GetCurrentThreadId();
- return true;
- }
- private:
- void InitializeMutex() { InitializeCriticalSection(&mutex_); }
-
- pthread_once_t initialize_token_;
- CRITICAL_SECTION mutex_;
-};
-
-class SpinLockHolder { // Acquires a spinlock for as long as the scope lasts
- private:
- SpinLock* lock_;
- public:
- inline explicit SpinLockHolder(SpinLock* l) : lock_(l) { l->Lock(); }
- inline ~SpinLockHolder() { lock_->Unlock(); }
-};
-#endif // #ifdef __cplusplus
-
-// This keeps us from using base/spinlock.h's implementation of SpinLock.
-#define BASE_SPINLOCK_H_ 1
-
-#endif /* #if 0 */
-
-/* ----------------------------------- MMAP and other memory allocation */
-
-#ifndef HAVE_MMAP /* not true for MSVC, but may be true for msys */
-#define MAP_FAILED 0
-#define MREMAP_FIXED 2 /* the value in linux, though it doesn't really matter */
-/* These, when combined with the mmap invariants below, yield the proper action */
-#define PROT_READ PAGE_READWRITE
-#define PROT_WRITE PAGE_READWRITE
-#define MAP_ANONYMOUS MEM_RESERVE
-#define MAP_PRIVATE MEM_COMMIT
-#define MAP_SHARED MEM_RESERVE /* value of this #define is 100% arbitrary */
-
-#if __STDC__ && !defined(__MINGW32__)
-typedef _off_t off_t;
-#endif
-
-/* VirtualAlloc only replaces for mmap when certain invariants are kept. */
-inline void *mmap(void *addr, size_t length, int prot, int flags,
- int fd, off_t offset) {
- if (addr == NULL && fd == -1 && offset == 0 &&
- prot == (PROT_READ|PROT_WRITE) && flags == (MAP_PRIVATE|MAP_ANONYMOUS)) {
- return VirtualAlloc(0, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
- } else {
- return NULL;
- }
-}
-
-inline int munmap(void *addr, size_t length) {
- return VirtualFree(addr, 0, MEM_RELEASE) ? 0 : -1;
-}
-#endif /* HAVE_MMAP */
-
-/* We could maybe use VirtualAlloc for sbrk as well, but no need */
-inline void *sbrk(intptr_t increment) {
- // sbrk returns -1 on failure
- return (void*)-1;
-}
-
-
-/* ----------------------------------- STRING ROUTINES */
-
-/*
- * We can't just use _vsnprintf and _snprintf as drop-in-replacements,
- * because they don't always NUL-terminate. :-( We also can't use the
- * name vsnprintf, since windows defines that (but not snprintf (!)).
- */
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-/* We can use safe CRT functions, which the required functionality */
-inline int perftools_vsnprintf(char *str, size_t size, const char *format,
- va_list ap) {
- return vsnprintf_s(str, size, _TRUNCATE, format, ap);
-}
-#else
-inline int perftools_vsnprintf(char *str, size_t size, const char *format,
- va_list ap) {
- if (size == 0) /* not even room for a \0? */
- return -1; /* not what C99 says to do, but what windows does */
- str[size-1] = '\0';
- return _vsnprintf(str, size-1, format, ap);
-}
-#endif
-
-#ifndef HAVE_SNPRINTF
-inline int snprintf(char *str, size_t size, const char *format, ...) {
- va_list ap;
- int r;
- va_start(ap, format);
- r = perftools_vsnprintf(str, size, format, ap);
- va_end(ap);
- return r;
-}
-#endif
-
-#define PRIx64 "I64x"
-#define SCNx64 "I64x"
-#define PRId64 "I64d"
-#define SCNd64 "I64d"
-#define PRIu64 "I64u"
-#ifdef _WIN64
-# define PRIuPTR "llu"
-# define PRIxPTR "llx"
-#else
-# define PRIuPTR "lu"
-# define PRIxPTR "lx"
-#endif
-
-/* ----------------------------------- FILE IO */
-
-#ifndef PATH_MAX
-#define PATH_MAX 1024
-#endif
-#ifndef __MINGW32__
-enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
-#endif
-#ifndef O_RDONLY
-#define O_RDONLY _O_RDONLY
-#endif
-
-#if __STDC__ && !defined(__MINGW32__)
-/* These functions are considered non-standard */
-inline int access(const char *pathname, int mode) {
- return _access(pathname, mode);
-}
-inline int open(const char *pathname, int flags, int mode = 0) {
- return _open(pathname, flags, mode);
-}
-inline int close(int fd) {
- return _close(fd);
-}
-inline ssize_t read(int fd, void *buf, size_t count) {
- return _read(fd, buf, count);
-}
-inline ssize_t write(int fd, const void *buf, size_t count) {
- return _write(fd, buf, count);
-}
-inline off_t lseek(int fd, off_t offset, int whence) {
- return _lseek(fd, offset, whence);
-}
-inline char *getcwd(char *buf, size_t size) {
- return _getcwd(buf, size);
-}
-inline int mkdir(const char *pathname, int) {
- return _mkdir(pathname);
-}
-
-inline FILE *popen(const char *command, const char *type) {
- return _popen(command, type);
-}
-inline int pclose(FILE *stream) {
- return _pclose(stream);
-}
-#endif
-
-EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
-
-/* ----------------------------------- SYSTEM/PROCESS */
-
-#ifndef HAVE_PID_T
-typedef int pid_t;
-#endif
-
-#if __STDC__ && !defined(__MINGW32__)
-inline pid_t getpid(void) { return _getpid(); }
-#endif
-inline pid_t getppid(void) { return 0; }
-
-/* Handle case when poll is used to simulate sleep. */
-inline int poll(struct pollfd* fds, int nfds, int timeout) {
- assert(fds == NULL);
- assert(nfds == 0);
- Sleep(timeout);
- return 0;
-}
-
-EXTERN_C PERFTOOLS_DLL_DECL int getpagesize(); /* in port.cc */
-
-/* ----------------------------------- OTHER */
-
-inline void srandom(unsigned int seed) { srand(seed); }
-inline long random(void) { return rand(); }
-
-#ifndef HAVE_DECL_SLEEP
-#define HAVE_DECL_SLEEP 0
-#endif
-
-#if !HAVE_DECL_SLEEP
-inline unsigned int sleep(unsigned int seconds) {
- Sleep(seconds * 1000);
- return 0;
-}
-#endif
-
-// mingw64 seems to define timespec (though mingw.org mingw doesn't),
-// protected by the _TIMESPEC_DEFINED macro.
-#ifndef _TIMESPEC_DEFINED
-struct timespec {
- int tv_sec;
- int tv_nsec;
-};
-#endif
-
-#ifndef HAVE_DECL_NANOSLEEP
-#define HAVE_DECL_NANOSLEEP 0
-#endif
-
-// latest mingw64 has nanosleep. Earlier mingw and MSVC do not
-#if !HAVE_DECL_NANOSLEEP
-inline int nanosleep(const struct timespec *req, struct timespec *rem) {
- Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
- return 0;
-}
-#endif
-
-#ifndef __MINGW32__
-#if defined(_MSC_VER) && _MSC_VER < 1800
-inline long long int strtoll(const char *nptr, char **endptr, int base) {
- return _strtoi64(nptr, endptr, base);
-}
-inline unsigned long long int strtoull(const char *nptr, char **endptr,
- int base) {
- return _strtoui64(nptr, endptr, base);
-}
-inline long long int strtoq(const char *nptr, char **endptr, int base) {
- return _strtoi64(nptr, endptr, base);
-}
-#endif
-inline unsigned long long int strtouq(const char *nptr, char **endptr,
- int base) {
- return _strtoui64(nptr, endptr, base);
-}
-inline long long atoll(const char *nptr) {
- return _atoi64(nptr);
-}
-#endif
-
-#define __THROW throw()
-
-/* ----------------------------------- TCMALLOC-SPECIFIC */
-
-/* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */
-extern void PatchWindowsFunctions();
-
-#endif /* _WIN32 */
-
-#undef inline
-#undef EXTERN_C
-
-#endif /* GOOGLE_BASE_WINDOWS_H_ */
diff --git a/src/third_party/gperftools-2.5/src/windows/preamble_patcher.cc b/src/third_party/gperftools-2.5/src/windows/preamble_patcher.cc
deleted file mode 100644
index ec055373c11..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/preamble_patcher.cc
+++ /dev/null
@@ -1,736 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2007, 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: Joi Sigurdsson
- * Author: Scott Francis
- *
- * Implementation of PreamblePatcher
- */
-
-#include "preamble_patcher.h"
-
-#include "mini_disassembler.h"
-
-// compatibility shims
-#include "base/logging.h"
-
-// Definitions of assembly statements we need
-#define ASM_JMP32REL 0xE9
-#define ASM_INT3 0xCC
-#define ASM_JMP32ABS_0 0xFF
-#define ASM_JMP32ABS_1 0x25
-#define ASM_JMP8REL 0xEB
-#define ASM_JCC32REL_0 0x0F
-#define ASM_JCC32REL_1_MASK 0x80
-#define ASM_NOP 0x90
-// X64 opcodes
-#define ASM_REXW 0x48
-#define ASM_MOVRAX_IMM 0xB8
-#define ASM_JMP 0xFF
-#define ASM_JMP_RAX 0xE0
-
-namespace sidestep {
-
-PreamblePatcher::PreamblePage* PreamblePatcher::preamble_pages_ = NULL;
-long PreamblePatcher::granularity_ = 0;
-long PreamblePatcher::pagesize_ = 0;
-bool PreamblePatcher::initialized_ = false;
-
-static const unsigned int kPreamblePageMagic = 0x4347414D; // "MAGC"
-
-// Handle a special case that we see with functions that point into an
-// IAT table (including functions linked statically into the
-// application): these function already starts with ASM_JMP32*. For
-// instance, malloc() might be implemented as a JMP to __malloc().
-// This function follows the initial JMPs for us, until we get to the
-// place where the actual code is defined. If we get to STOP_BEFORE,
-// we return the address before stop_before. The stop_before_trampoline
-// flag is used in 64-bit mode. If true, we will return the address
-// before a trampoline is detected. Trampolines are defined as:
-//
-// nop
-// mov rax, <replacement_function>
-// jmp rax
-//
-// See PreamblePatcher::RawPatchWithStub for more information.
-void* PreamblePatcher::ResolveTargetImpl(unsigned char* target,
- unsigned char* stop_before,
- bool stop_before_trampoline) {
- if (target == NULL)
- return NULL;
- while (1) {
- unsigned char* new_target;
- if (target[0] == ASM_JMP32REL) {
- // target[1-4] holds the place the jmp goes to, but it's
- // relative to the next instruction.
- int relative_offset; // Windows guarantees int is 4 bytes
- SIDESTEP_ASSERT(sizeof(relative_offset) == 4);
- memcpy(reinterpret_cast<void*>(&relative_offset),
- reinterpret_cast<void*>(target + 1), 4);
- new_target = target + 5 + relative_offset;
- } else if (target[0] == ASM_JMP8REL) {
- // Visual Studio 7.1 implements new[] as an 8 bit jump to new
- signed char relative_offset;
- memcpy(reinterpret_cast<void*>(&relative_offset),
- reinterpret_cast<void*>(target + 1), 1);
- new_target = target + 2 + relative_offset;
- } else if (target[0] == ASM_JMP32ABS_0 &&
- target[1] == ASM_JMP32ABS_1) {
- jmp32rel:
- // Visual studio seems to sometimes do it this way instead of the
- // previous way. Not sure what the rules are, but it was happening
- // with operator new in some binaries.
- void** new_target_v;
- if (kIs64BitBinary) {
- // In 64-bit mode JMPs are RIP-relative, not absolute
- int target_offset;
- memcpy(reinterpret_cast<void*>(&target_offset),
- reinterpret_cast<void*>(target + 2), 4);
- new_target_v = reinterpret_cast<void**>(target + target_offset + 6);
- } else {
- SIDESTEP_ASSERT(sizeof(new_target) == 4);
- memcpy(&new_target_v, reinterpret_cast<void*>(target + 2), 4);
- }
- new_target = reinterpret_cast<unsigned char*>(*new_target_v);
- } else if (kIs64BitBinary && target[0] == ASM_REXW
- && target[1] == ASM_JMP32ABS_0
- && target[2] == ASM_JMP32ABS_1) {
- // in Visual Studio 2012 we're seeing jump like that:
- // rex.W jmpq *0x11d019(%rip)
- //
- // according to docs I have, rex prefix is actually unneeded and
- // can be ignored. I.e. docs say for jumps like that operand
- // already defaults to 64-bit. But clearly it breaks abs. jump
- // detection above and we just skip rex
- target++;
- goto jmp32rel;
- } else {
- break;
- }
- if (new_target == stop_before)
- break;
- if (stop_before_trampoline && *new_target == ASM_NOP
- && new_target[1] == ASM_REXW && new_target[2] == ASM_MOVRAX_IMM)
- break;
- target = new_target;
- }
- return target;
-}
-
-// Special case scoped_ptr to avoid dependency on scoped_ptr below.
-class DeleteUnsignedCharArray {
- public:
- DeleteUnsignedCharArray(unsigned char* array) : array_(array) {
- }
-
- ~DeleteUnsignedCharArray() {
- if (array_) {
- PreamblePatcher::FreePreambleBlock(array_);
- }
- }
-
- unsigned char* Release() {
- unsigned char* temp = array_;
- array_ = NULL;
- return temp;
- }
-
- private:
- unsigned char* array_;
-};
-
-SideStepError PreamblePatcher::RawPatchWithStubAndProtections(
- void* target_function, void *replacement_function,
- unsigned char* preamble_stub, unsigned long stub_size,
- unsigned long* bytes_needed) {
- // We need to be able to write to a process-local copy of the first
- // MAX_PREAMBLE_STUB_SIZE bytes of target_function
- DWORD old_target_function_protect = 0;
- BOOL succeeded = ::VirtualProtect(reinterpret_cast<void*>(target_function),
- MAX_PREAMBLE_STUB_SIZE,
- PAGE_EXECUTE_READWRITE,
- &old_target_function_protect);
- if (!succeeded) {
- SIDESTEP_ASSERT(false && "Failed to make page containing target function "
- "copy-on-write.");
- return SIDESTEP_ACCESS_DENIED;
- }
-
- SideStepError error_code = RawPatchWithStub(target_function,
- replacement_function,
- preamble_stub,
- stub_size,
- bytes_needed);
-
- // Restore the protection of the first MAX_PREAMBLE_STUB_SIZE bytes of
- // pTargetFunction to what they were before we started goofing around.
- // We do this regardless of whether the patch succeeded or not.
- succeeded = ::VirtualProtect(reinterpret_cast<void*>(target_function),
- MAX_PREAMBLE_STUB_SIZE,
- old_target_function_protect,
- &old_target_function_protect);
- if (!succeeded) {
- SIDESTEP_ASSERT(false &&
- "Failed to restore protection to target function.");
- // We must not return an error here because the function has
- // likely actually been patched, and returning an error might
- // cause our client code not to unpatch it. So we just keep
- // going.
- }
-
- if (SIDESTEP_SUCCESS != error_code) { // Testing RawPatchWithStub, above
- SIDESTEP_ASSERT(false);
- return error_code;
- }
-
- // Flush the instruction cache to make sure the processor doesn't execute the
- // old version of the instructions (before our patch).
- //
- // FlushInstructionCache is actually a no-op at least on
- // single-processor XP machines. I'm not sure why this is so, but
- // it is, yet I want to keep the call to the API here for
- // correctness in case there is a difference in some variants of
- // Windows/hardware.
- succeeded = ::FlushInstructionCache(::GetCurrentProcess(),
- target_function,
- MAX_PREAMBLE_STUB_SIZE);
- if (!succeeded) {
- SIDESTEP_ASSERT(false && "Failed to flush instruction cache.");
- // We must not return an error here because the function has actually
- // been patched, and returning an error would likely cause our client
- // code not to unpatch it. So we just keep going.
- }
-
- return SIDESTEP_SUCCESS;
-}
-
-SideStepError PreamblePatcher::RawPatch(void* target_function,
- void* replacement_function,
- void** original_function_stub) {
- if (!target_function || !replacement_function || !original_function_stub ||
- (*original_function_stub) || target_function == replacement_function) {
- SIDESTEP_ASSERT(false && "Preconditions not met");
- return SIDESTEP_INVALID_PARAMETER;
- }
-
- BOOL succeeded = FALSE;
-
- // First, deal with a special case that we see with functions that
- // point into an IAT table (including functions linked statically
- // into the application): these function already starts with
- // ASM_JMP32REL. For instance, malloc() might be implemented as a
- // JMP to __malloc(). In that case, we replace the destination of
- // the JMP (__malloc), rather than the JMP itself (malloc). This
- // way we get the correct behavior no matter how malloc gets called.
- void* new_target = ResolveTarget(target_function);
- if (new_target != target_function) {
- target_function = new_target;
- }
-
- // In 64-bit mode, preamble_stub must be within 2GB of target function
- // so that if target contains a jump, we can translate it.
- unsigned char* preamble_stub = AllocPreambleBlockNear(target_function);
- if (!preamble_stub) {
- SIDESTEP_ASSERT(false && "Unable to allocate preamble-stub.");
- return SIDESTEP_INSUFFICIENT_BUFFER;
- }
-
- // Frees the array at end of scope.
- DeleteUnsignedCharArray guard_preamble_stub(preamble_stub);
-
- SideStepError error_code = RawPatchWithStubAndProtections(
- target_function, replacement_function, preamble_stub,
- MAX_PREAMBLE_STUB_SIZE, NULL);
-
- if (SIDESTEP_SUCCESS != error_code) {
- SIDESTEP_ASSERT(false);
- return error_code;
- }
-
- // Flush the instruction cache to make sure the processor doesn't execute the
- // old version of the instructions (before our patch).
- //
- // FlushInstructionCache is actually a no-op at least on
- // single-processor XP machines. I'm not sure why this is so, but
- // it is, yet I want to keep the call to the API here for
- // correctness in case there is a difference in some variants of
- // Windows/hardware.
- succeeded = ::FlushInstructionCache(::GetCurrentProcess(),
- target_function,
- MAX_PREAMBLE_STUB_SIZE);
- if (!succeeded) {
- SIDESTEP_ASSERT(false && "Failed to flush instruction cache.");
- // We must not return an error here because the function has actually
- // been patched, and returning an error would likely cause our client
- // code not to unpatch it. So we just keep going.
- }
-
- SIDESTEP_LOG("PreamblePatcher::RawPatch successfully patched.");
-
- // detach the scoped pointer so the memory is not freed
- *original_function_stub =
- reinterpret_cast<void*>(guard_preamble_stub.Release());
- return SIDESTEP_SUCCESS;
-}
-
-SideStepError PreamblePatcher::Unpatch(void* target_function,
- void* replacement_function,
- void* original_function_stub) {
- SIDESTEP_ASSERT(target_function && replacement_function &&
- original_function_stub);
- if (!target_function || !replacement_function ||
- !original_function_stub) {
- return SIDESTEP_INVALID_PARAMETER;
- }
-
- // Before unpatching, target_function should be a JMP to
- // replacement_function. If it's not, then either it's an error, or
- // we're falling into the case where the original instruction was a
- // JMP, and we patched the jumped_to address rather than the JMP
- // itself. (For instance, if malloc() is just a JMP to __malloc(),
- // we patched __malloc() and not malloc().)
- unsigned char* target = reinterpret_cast<unsigned char*>(target_function);
- target = reinterpret_cast<unsigned char*>(
- ResolveTargetImpl(
- target, reinterpret_cast<unsigned char*>(replacement_function),
- true));
- // We should end at the function we patched. When we patch, we insert
- // a ASM_JMP32REL instruction, so look for that as a sanity check.
- if (target[0] != ASM_JMP32REL) {
- SIDESTEP_ASSERT(false &&
- "target_function does not look like it was patched.");
- return SIDESTEP_INVALID_PARAMETER;
- }
-
- const unsigned int kRequiredTargetPatchBytes = 5;
-
- // We need to be able to write to a process-local copy of the first
- // kRequiredTargetPatchBytes bytes of target_function
- DWORD old_target_function_protect = 0;
- BOOL succeeded = ::VirtualProtect(reinterpret_cast<void*>(target),
- kRequiredTargetPatchBytes,
- PAGE_EXECUTE_READWRITE,
- &old_target_function_protect);
- if (!succeeded) {
- SIDESTEP_ASSERT(false && "Failed to make page containing target function "
- "copy-on-write.");
- return SIDESTEP_ACCESS_DENIED;
- }
-
- unsigned char* preamble_stub = reinterpret_cast<unsigned char*>(
- original_function_stub);
-
- // Disassemble the preamble of stub and copy the bytes back to target.
- // If we've done any conditional jumps in the preamble we need to convert
- // them back to the original REL8 jumps in the target.
- MiniDisassembler disassembler;
- unsigned int preamble_bytes = 0;
- unsigned int target_bytes = 0;
- while (target_bytes < kRequiredTargetPatchBytes) {
- unsigned int cur_bytes = 0;
- InstructionType instruction_type =
- disassembler.Disassemble(preamble_stub + preamble_bytes, cur_bytes);
- if (IT_JUMP == instruction_type) {
- unsigned int jump_bytes = 0;
- SideStepError jump_ret = SIDESTEP_JUMP_INSTRUCTION;
- if (IsNearConditionalJump(preamble_stub + preamble_bytes, cur_bytes) ||
- IsNearRelativeJump(preamble_stub + preamble_bytes, cur_bytes) ||
- IsNearAbsoluteCall(preamble_stub + preamble_bytes, cur_bytes) ||
- IsNearRelativeCall(preamble_stub + preamble_bytes, cur_bytes)) {
- jump_ret = PatchNearJumpOrCall(preamble_stub + preamble_bytes,
- cur_bytes, target + target_bytes,
- &jump_bytes, MAX_PREAMBLE_STUB_SIZE);
- }
- if (jump_ret == SIDESTEP_JUMP_INSTRUCTION) {
- SIDESTEP_ASSERT(false &&
- "Found unsupported jump instruction in stub!!");
- return SIDESTEP_UNSUPPORTED_INSTRUCTION;
- }
- target_bytes += jump_bytes;
- } else if (IT_GENERIC == instruction_type) {
- if (IsMovWithDisplacement(preamble_stub + preamble_bytes, cur_bytes)) {
- unsigned int mov_bytes = 0;
- if (PatchMovWithDisplacement(preamble_stub + preamble_bytes, cur_bytes,
- target + target_bytes, &mov_bytes,
- MAX_PREAMBLE_STUB_SIZE)
- != SIDESTEP_SUCCESS) {
- SIDESTEP_ASSERT(false &&
- "Found unsupported generic instruction in stub!!");
- return SIDESTEP_UNSUPPORTED_INSTRUCTION;
- }
- } else {
- memcpy(reinterpret_cast<void*>(target + target_bytes),
- reinterpret_cast<void*>(reinterpret_cast<unsigned char*>(
- original_function_stub) + preamble_bytes), cur_bytes);
- target_bytes += cur_bytes;
- }
- } else {
- SIDESTEP_ASSERT(false &&
- "Found unsupported instruction in stub!!");
- return SIDESTEP_UNSUPPORTED_INSTRUCTION;
- }
- preamble_bytes += cur_bytes;
- }
-
- FreePreambleBlock(reinterpret_cast<unsigned char*>(original_function_stub));
-
- // Restore the protection of the first kRequiredTargetPatchBytes bytes of
- // target to what they were before we started goofing around.
- succeeded = ::VirtualProtect(reinterpret_cast<void*>(target),
- kRequiredTargetPatchBytes,
- old_target_function_protect,
- &old_target_function_protect);
-
- // Flush the instruction cache to make sure the processor doesn't execute the
- // old version of the instructions (before our patch).
- //
- // See comment on FlushInstructionCache elsewhere in this file.
- succeeded = ::FlushInstructionCache(::GetCurrentProcess(),
- target,
- MAX_PREAMBLE_STUB_SIZE);
- if (!succeeded) {
- SIDESTEP_ASSERT(false && "Failed to flush instruction cache.");
- return SIDESTEP_UNEXPECTED;
- }
-
- SIDESTEP_LOG("PreamblePatcher::Unpatch successfully unpatched.");
- return SIDESTEP_SUCCESS;
-}
-
-void PreamblePatcher::Initialize() {
- if (!initialized_) {
- SYSTEM_INFO si = { 0 };
- ::GetSystemInfo(&si);
- granularity_ = si.dwAllocationGranularity;
- pagesize_ = si.dwPageSize;
- initialized_ = true;
- }
-}
-
-unsigned char* PreamblePatcher::AllocPreambleBlockNear(void* target) {
- PreamblePage* preamble_page = preamble_pages_;
- while (preamble_page != NULL) {
- if (preamble_page->free_ != NULL) {
- __int64 val = reinterpret_cast<__int64>(preamble_page) -
- reinterpret_cast<__int64>(target);
- if ((val > 0 && val + pagesize_ <= INT_MAX) ||
- (val < 0 && val >= INT_MIN)) {
- break;
- }
- }
- preamble_page = preamble_page->next_;
- }
-
- // The free_ member of the page is used to store the next available block
- // of memory to use or NULL if there are no chunks available, in which case
- // we'll allocate a new page.
- if (preamble_page == NULL || preamble_page->free_ == NULL) {
- // Create a new preamble page and initialize the free list
- preamble_page = reinterpret_cast<PreamblePage*>(AllocPageNear(target));
- SIDESTEP_ASSERT(preamble_page != NULL && "Could not allocate page!");
- void** pp = &preamble_page->free_;
- unsigned char* ptr = reinterpret_cast<unsigned char*>(preamble_page) +
- MAX_PREAMBLE_STUB_SIZE;
- unsigned char* limit = reinterpret_cast<unsigned char*>(preamble_page) +
- pagesize_;
- while (ptr < limit) {
- *pp = ptr;
- pp = reinterpret_cast<void**>(ptr);
- ptr += MAX_PREAMBLE_STUB_SIZE;
- }
- *pp = NULL;
- // Insert the new page into the list
- preamble_page->magic_ = kPreamblePageMagic;
- preamble_page->next_ = preamble_pages_;
- preamble_pages_ = preamble_page;
- }
- unsigned char* ret = reinterpret_cast<unsigned char*>(preamble_page->free_);
- preamble_page->free_ = *(reinterpret_cast<void**>(preamble_page->free_));
- return ret;
-}
-
-void PreamblePatcher::FreePreambleBlock(unsigned char* block) {
- SIDESTEP_ASSERT(block != NULL);
- SIDESTEP_ASSERT(granularity_ != 0);
- uintptr_t ptr = reinterpret_cast<uintptr_t>(block);
- ptr -= ptr & (granularity_ - 1);
- PreamblePage* preamble_page = reinterpret_cast<PreamblePage*>(ptr);
- SIDESTEP_ASSERT(preamble_page->magic_ == kPreamblePageMagic);
- *(reinterpret_cast<void**>(block)) = preamble_page->free_;
- preamble_page->free_ = block;
-}
-
-void* PreamblePatcher::AllocPageNear(void* target) {
- MEMORY_BASIC_INFORMATION mbi = { 0 };
- if (!::VirtualQuery(target, &mbi, sizeof(mbi))) {
- SIDESTEP_ASSERT(false && "VirtualQuery failed on target address");
- return 0;
- }
- if (initialized_ == false) {
- PreamblePatcher::Initialize();
- SIDESTEP_ASSERT(initialized_);
- }
- void* pv = NULL;
- unsigned char* allocation_base = reinterpret_cast<unsigned char*>(
- mbi.AllocationBase);
- __int64 i = 1;
- bool high_target = reinterpret_cast<__int64>(target) > UINT_MAX;
- while (pv == NULL) {
- __int64 val = reinterpret_cast<__int64>(allocation_base) -
- (i * granularity_);
- if (high_target &&
- reinterpret_cast<__int64>(target) - val > INT_MAX) {
- // We're further than 2GB from the target
- break;
- } else if (val <= NULL) {
- // Less than 0
- break;
- }
- pv = ::VirtualAlloc(reinterpret_cast<void*>(allocation_base -
- (i++ * granularity_)),
- pagesize_, MEM_COMMIT | MEM_RESERVE,
- PAGE_EXECUTE_READWRITE);
- }
-
- // We couldn't allocate low, try to allocate high
- if (pv == NULL) {
- i = 1;
- // Round up to the next multiple of page granularity
- allocation_base = reinterpret_cast<unsigned char*>(
- (reinterpret_cast<__int64>(target) &
- (~(granularity_ - 1))) + granularity_);
- while (pv == NULL) {
- __int64 val = reinterpret_cast<__int64>(allocation_base) +
- (i * granularity_) - reinterpret_cast<__int64>(target);
- if (val > INT_MAX || val < 0) {
- // We're too far or we overflowed
- break;
- }
- pv = ::VirtualAlloc(reinterpret_cast<void*>(allocation_base +
- (i++ * granularity_)),
- pagesize_, MEM_COMMIT | MEM_RESERVE,
- PAGE_EXECUTE_READWRITE);
- }
- }
- return pv;
-}
-
-bool PreamblePatcher::IsShortConditionalJump(
- unsigned char* target,
- unsigned int instruction_size) {
- return (*(target) & 0x70) == 0x70 && instruction_size == 2;
-}
-
-bool PreamblePatcher::IsShortJump(
- unsigned char* target,
- unsigned int instruction_size) {
- return target[0] == 0xeb && instruction_size == 2;
-}
-
-bool PreamblePatcher::IsNearConditionalJump(
- unsigned char* target,
- unsigned int instruction_size) {
- return *(target) == 0xf && (*(target + 1) & 0x80) == 0x80 &&
- instruction_size == 6;
-}
-
-bool PreamblePatcher::IsNearRelativeJump(
- unsigned char* target,
- unsigned int instruction_size) {
- return *(target) == 0xe9 && instruction_size == 5;
-}
-
-bool PreamblePatcher::IsNearAbsoluteCall(
- unsigned char* target,
- unsigned int instruction_size) {
- return *(target) == 0xff && (*(target + 1) & 0x10) == 0x10 &&
- instruction_size == 6;
-}
-
-bool PreamblePatcher::IsNearRelativeCall(
- unsigned char* target,
- unsigned int instruction_size) {
- return *(target) == 0xe8 && instruction_size == 5;
-}
-
-bool PreamblePatcher::IsMovWithDisplacement(
- unsigned char* target,
- unsigned int instruction_size) {
- // In this case, the ModRM byte's mod field will be 0 and r/m will be 101b (5)
- return instruction_size == 7 && *target == 0x48 && *(target + 1) == 0x8b &&
- (*(target + 2) >> 6) == 0 && (*(target + 2) & 0x7) == 5;
-}
-
-SideStepError PreamblePatcher::PatchShortConditionalJump(
- unsigned char* source,
- unsigned int instruction_size,
- unsigned char* target,
- unsigned int* target_bytes,
- unsigned int target_size) {
- // note: rel8 offset is signed. Thus we need to ask for signed char
- // to negative offsets right
- unsigned char* original_jump_dest = (source + 2) + static_cast<signed char>(source[1]);
- unsigned char* stub_jump_from = target + 6;
- __int64 fixup_jump_offset = original_jump_dest - stub_jump_from;
- if (fixup_jump_offset > INT_MAX || fixup_jump_offset < INT_MIN) {
- SIDESTEP_ASSERT(false &&
- "Unable to fix up short jump because target"
- " is too far away.");
- return SIDESTEP_JUMP_INSTRUCTION;
- }
-
- *target_bytes = 6;
- if (target_size > *target_bytes) {
- // Convert the short jump to a near jump.
- //
- // 0f 8x xx xx xx xx = Jcc rel32off
- unsigned short jmpcode = ((0x80 | (source[0] & 0xf)) << 8) | 0x0f;
- memcpy(reinterpret_cast<void*>(target),
- reinterpret_cast<void*>(&jmpcode), 2);
- memcpy(reinterpret_cast<void*>(target + 2),
- reinterpret_cast<void*>(&fixup_jump_offset), 4);
- }
-
- return SIDESTEP_SUCCESS;
-}
-
-SideStepError PreamblePatcher::PatchShortJump(
- unsigned char* source,
- unsigned int instruction_size,
- unsigned char* target,
- unsigned int* target_bytes,
- unsigned int target_size) {
- // note: rel8 offset is _signed_. Thus we need signed char here.
- unsigned char* original_jump_dest = (source + 2) + static_cast<signed char>(source[1]);
- unsigned char* stub_jump_from = target + 5;
- __int64 fixup_jump_offset = original_jump_dest - stub_jump_from;
- if (fixup_jump_offset > INT_MAX || fixup_jump_offset < INT_MIN) {
- SIDESTEP_ASSERT(false &&
- "Unable to fix up short jump because target"
- " is too far away.");
- return SIDESTEP_JUMP_INSTRUCTION;
- }
-
- *target_bytes = 5;
- if (target_size > *target_bytes) {
- // Convert the short jump to a near jump.
- //
- // e9 xx xx xx xx = jmp rel32off
- target[0] = 0xe9;
- memcpy(reinterpret_cast<void*>(target + 1),
- reinterpret_cast<void*>(&fixup_jump_offset), 4);
- }
-
- return SIDESTEP_SUCCESS;
-}
-
-SideStepError PreamblePatcher::PatchNearJumpOrCall(
- unsigned char* source,
- unsigned int instruction_size,
- unsigned char* target,
- unsigned int* target_bytes,
- unsigned int target_size) {
- SIDESTEP_ASSERT(instruction_size == 5 || instruction_size == 6);
- unsigned int jmp_offset_in_instruction = instruction_size == 5 ? 1 : 2;
- unsigned char* original_jump_dest = reinterpret_cast<unsigned char *>(
- reinterpret_cast<__int64>(source + instruction_size) +
- *(reinterpret_cast<int*>(source + jmp_offset_in_instruction)));
- unsigned char* stub_jump_from = target + instruction_size;
- __int64 fixup_jump_offset = original_jump_dest - stub_jump_from;
- if (fixup_jump_offset > INT_MAX || fixup_jump_offset < INT_MIN) {
- SIDESTEP_ASSERT(false &&
- "Unable to fix up near jump because target"
- " is too far away.");
- return SIDESTEP_JUMP_INSTRUCTION;
- }
-
- if ((fixup_jump_offset < SCHAR_MAX && fixup_jump_offset > SCHAR_MIN)) {
- *target_bytes = 2;
- if (target_size > *target_bytes) {
- // If the new offset is in range, use a short jump instead of a near jump.
- if (source[0] == ASM_JCC32REL_0 &&
- (source[1] & ASM_JCC32REL_1_MASK) == ASM_JCC32REL_1_MASK) {
- unsigned short jmpcode = (static_cast<unsigned char>(
- fixup_jump_offset) << 8) | (0x70 | (source[1] & 0xf));
- memcpy(reinterpret_cast<void*>(target),
- reinterpret_cast<void*>(&jmpcode),
- 2);
- } else {
- target[0] = ASM_JMP8REL;
- target[1] = static_cast<unsigned char>(fixup_jump_offset);
- }
- }
- } else {
- *target_bytes = instruction_size;
- if (target_size > *target_bytes) {
- memcpy(reinterpret_cast<void*>(target),
- reinterpret_cast<void*>(source),
- jmp_offset_in_instruction);
- memcpy(reinterpret_cast<void*>(target + jmp_offset_in_instruction),
- reinterpret_cast<void*>(&fixup_jump_offset),
- 4);
- }
- }
-
- return SIDESTEP_SUCCESS;
-}
-
-SideStepError PreamblePatcher::PatchMovWithDisplacement(
- unsigned char* source,
- unsigned int instruction_size,
- unsigned char* target,
- unsigned int* target_bytes,
- unsigned int target_size) {
- SIDESTEP_ASSERT(instruction_size == 7);
- const int mov_offset_in_instruction = 3; // 0x48 0x8b 0x0d <offset>
- unsigned char* original_mov_dest = reinterpret_cast<unsigned char*>(
- reinterpret_cast<__int64>(source + instruction_size) +
- *(reinterpret_cast<int*>(source + mov_offset_in_instruction)));
- unsigned char* stub_mov_from = target + instruction_size;
- __int64 fixup_mov_offset = original_mov_dest - stub_mov_from;
- if (fixup_mov_offset > INT_MAX || fixup_mov_offset < INT_MIN) {
- SIDESTEP_ASSERT(false &&
- "Unable to fix up near MOV because target is too far away.");
- return SIDESTEP_UNEXPECTED;
- }
- *target_bytes = instruction_size;
- if (target_size > *target_bytes) {
- memcpy(reinterpret_cast<void*>(target),
- reinterpret_cast<void*>(source),
- mov_offset_in_instruction);
- memcpy(reinterpret_cast<void*>(target + mov_offset_in_instruction),
- reinterpret_cast<void*>(&fixup_mov_offset),
- 4);
- }
- return SIDESTEP_SUCCESS;
-}
-
-}; // namespace sidestep
diff --git a/src/third_party/gperftools-2.5/src/windows/preamble_patcher.h b/src/third_party/gperftools-2.5/src/windows/preamble_patcher.h
deleted file mode 100644
index 76f158a19a1..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/preamble_patcher.h
+++ /dev/null
@@ -1,620 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2007, 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: Joi Sigurdsson
- * Author: Scott Francis
- *
- * Definition of PreamblePatcher
- */
-
-#ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
-#define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
-
-#include "config.h"
-#include <windows.h>
-
-// compatibility shim
-#include "base/logging.h"
-#define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond)
-#define SIDESTEP_LOG(msg) RAW_VLOG(1, msg)
-
-// Maximum size of the preamble stub. We overwrite at least the first 5
-// bytes of the function. Considering the worst case scenario, we need 4
-// bytes + the max instruction size + 5 more bytes for our jump back to
-// the original code. With that in mind, 32 is a good number :)
-#ifdef _M_X64
-// In 64-bit mode we may need more room. In 64-bit mode all jumps must be
-// within +/-2GB of RIP. Because of this limitation we may need to use a
-// trampoline to jump to the replacement function if it is further than 2GB
-// away from the target. The trampoline is 14 bytes.
-//
-// So 4 bytes + max instruction size (17 bytes) + 5 bytes to jump back to the
-// original code + trampoline size. 64 bytes is a nice number :-)
-#define MAX_PREAMBLE_STUB_SIZE (64)
-#else
-#define MAX_PREAMBLE_STUB_SIZE (32)
-#endif
-
-// Determines if this is a 64-bit binary.
-#ifdef _M_X64
-static const bool kIs64BitBinary = true;
-#else
-static const bool kIs64BitBinary = false;
-#endif
-
-namespace sidestep {
-
-// Possible results of patching/unpatching
-enum SideStepError {
- SIDESTEP_SUCCESS = 0,
- SIDESTEP_INVALID_PARAMETER,
- SIDESTEP_INSUFFICIENT_BUFFER,
- SIDESTEP_JUMP_INSTRUCTION,
- SIDESTEP_FUNCTION_TOO_SMALL,
- SIDESTEP_UNSUPPORTED_INSTRUCTION,
- SIDESTEP_NO_SUCH_MODULE,
- SIDESTEP_NO_SUCH_FUNCTION,
- SIDESTEP_ACCESS_DENIED,
- SIDESTEP_UNEXPECTED,
-};
-
-#define SIDESTEP_TO_HRESULT(error) \
- MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error)
-
-class DeleteUnsignedCharArray;
-
-// Implements a patching mechanism that overwrites the first few bytes of
-// a function preamble with a jump to our hook function, which is then
-// able to call the original function via a specially-made preamble-stub
-// that imitates the action of the original preamble.
-//
-// NOTE: This patching mechanism should currently only be used for
-// non-production code, e.g. unit tests, because it is not threadsafe.
-// See the TODO in preamble_patcher_with_stub.cc for instructions on what
-// we need to do before using it in production code; it's fairly simple
-// but unnecessary for now since we only intend to use it in unit tests.
-//
-// To patch a function, use either of the typesafe Patch() methods. You
-// can unpatch a function using Unpatch().
-//
-// Typical usage goes something like this:
-// @code
-// typedef int (*MyTypesafeFuncPtr)(int x);
-// MyTypesafeFuncPtr original_func_stub;
-// int MyTypesafeFunc(int x) { return x + 1; }
-// int HookMyTypesafeFunc(int x) { return 1 + original_func_stub(x); }
-//
-// void MyPatchInitializingFunction() {
-// original_func_stub = PreamblePatcher::Patch(
-// MyTypesafeFunc, HookMyTypesafeFunc);
-// if (!original_func_stub) {
-// // ... error handling ...
-// }
-//
-// // ... continue - you have patched the function successfully ...
-// }
-// @endcode
-//
-// Note that there are a number of ways that this method of patching can
-// fail. The most common are:
-// - If there is a jump (jxx) instruction in the first 5 bytes of
-// the function being patched, we cannot patch it because in the
-// current implementation we do not know how to rewrite relative
-// jumps after relocating them to the preamble-stub. Note that
-// if you really really need to patch a function like this, it
-// would be possible to add this functionality (but at some cost).
-// - If there is a return (ret) instruction in the first 5 bytes
-// we cannot patch the function because it may not be long enough
-// for the jmp instruction we use to inject our patch.
-// - If there is another thread currently executing within the bytes
-// that are copied to the preamble stub, it will crash in an undefined
-// way.
-//
-// If you get any other error than the above, you're either pointing the
-// patcher at an invalid instruction (e.g. into the middle of a multi-
-// byte instruction, or not at memory containing executable instructions)
-// or, there may be a bug in the disassembler we use to find
-// instruction boundaries.
-//
-// NOTE: In optimized builds, when you have very trivial functions that
-// the compiler can reason do not have side effects, the compiler may
-// reuse the result of calling the function with a given parameter, which
-// may mean if you patch the function in between your patch will never get
-// invoked. See preamble_patcher_test.cc for an example.
-class PERFTOOLS_DLL_DECL PreamblePatcher {
- public:
-
- // This is a typesafe version of RawPatch(), identical in all other
- // ways than it takes a template parameter indicating the type of the
- // function being patched.
- //
- // @param T The type of the function you are patching. Usually
- // you will establish this type using a typedef, as in the following
- // example:
- // @code
- // typedef BOOL (WINAPI *MessageBoxPtr)(HWND, LPCTSTR, LPCTSTR, UINT);
- // MessageBoxPtr original = NULL;
- // PreamblePatcher::Patch(MessageBox, Hook_MessageBox, &original);
- // @endcode
- template <class T>
- static SideStepError Patch(T target_function,
- T replacement_function,
- T* original_function_stub) {
- // NOTE: casting from a function to a pointer is contra the C++
- // spec. It's not safe on IA64, but is on i386. We use
- // a C-style cast here to emphasize this is not legal C++.
- return RawPatch((void*)(target_function),
- (void*)(replacement_function),
- (void**)(original_function_stub));
- }
-
- // Patches a named function imported from the named module using
- // preamble patching. Uses RawPatch() to do the actual patching
- // work.
- //
- // @param T The type of the function you are patching. Must
- // exactly match the function you specify using module_name and
- // function_name.
- //
- // @param module_name The name of the module from which the function
- // is being imported. Note that the patch will fail if this module
- // has not already been loaded into the current process.
- //
- // @param function_name The name of the function you wish to patch.
- //
- // @param replacement_function Your replacement function which
- // will be called whenever code tries to call the original function.
- //
- // @param original_function_stub Pointer to memory that should receive a
- // pointer that can be used (e.g. in the replacement function) to call the
- // original function, or NULL to indicate failure.
- //
- // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
- // indicates success.
- template <class T>
- static SideStepError Patch(LPCTSTR module_name,
- LPCSTR function_name,
- T replacement_function,
- T* original_function_stub) {
- SIDESTEP_ASSERT(module_name && function_name);
- if (!module_name || !function_name) {
- SIDESTEP_ASSERT(false &&
- "You must specify a module name and function name.");
- return SIDESTEP_INVALID_PARAMETER;
- }
- HMODULE module = ::GetModuleHandle(module_name);
- SIDESTEP_ASSERT(module != NULL);
- if (!module) {
- SIDESTEP_ASSERT(false && "Invalid module name.");
- return SIDESTEP_NO_SUCH_MODULE;
- }
- FARPROC existing_function = ::GetProcAddress(module, function_name);
- if (!existing_function) {
- SIDESTEP_ASSERT(
- false && "Did not find any function with that name in the module.");
- return SIDESTEP_NO_SUCH_FUNCTION;
- }
- // NOTE: casting from a function to a pointer is contra the C++
- // spec. It's not safe on IA64, but is on i386. We use
- // a C-style cast here to emphasize this is not legal C++.
- return RawPatch((void*)existing_function, (void*)replacement_function,
- (void**)(original_function_stub));
- }
-
- // Patches a function by overwriting its first few bytes with
- // a jump to a different function. This is the "worker" function
- // for each of the typesafe Patch() functions. In most cases,
- // it is preferable to use the Patch() functions rather than
- // this one as they do more checking at compile time.
- //
- // @param target_function A pointer to the function that should be
- // patched.
- //
- // @param replacement_function A pointer to the function that should
- // replace the target function. The replacement function must have
- // exactly the same calling convention and parameters as the original
- // function.
- //
- // @param original_function_stub Pointer to memory that should receive a
- // pointer that can be used (e.g. in the replacement function) to call the
- // original function, or NULL to indicate failure.
- //
- // @param original_function_stub Pointer to memory that should receive a
- // pointer that can be used (e.g. in the replacement function) to call the
- // original function, or NULL to indicate failure.
- //
- // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
- // indicates success.
- //
- // @note The preamble-stub (the memory pointed to by
- // *original_function_stub) is allocated on the heap, and (in
- // production binaries) never destroyed, resulting in a memory leak. This
- // will be the case until we implement safe unpatching of a method.
- // However, it is quite difficult to unpatch a method (because other
- // threads in the process may be using it) so we are leaving it for now.
- // See however UnsafeUnpatch, which can be used for binaries where you
- // know only one thread is running, e.g. unit tests.
- static SideStepError RawPatch(void* target_function,
- void* replacement_function,
- void** original_function_stub);
-
- // Unpatches target_function and deletes the stub that previously could be
- // used to call the original version of the function.
- //
- // DELETES the stub that is passed to the function.
- //
- // @param target_function Pointer to the target function which was
- // previously patched, i.e. a pointer which value should match the value
- // of the symbol prior to patching it.
- //
- // @param replacement_function Pointer to the function target_function
- // was patched to.
- //
- // @param original_function_stub Pointer to the stub returned when
- // patching, that could be used to call the original version of the
- // patched function. This function will also delete the stub, which after
- // unpatching is useless.
- //
- // If your original call was
- // Patch(VirtualAlloc, MyVirtualAlloc, &origptr)
- // then to undo it you would call
- // Unpatch(VirtualAlloc, MyVirtualAlloc, origptr);
- //
- // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
- // indicates success.
- static SideStepError Unpatch(void* target_function,
- void* replacement_function,
- void* original_function_stub);
-
- // A helper routine when patching, which follows jmp instructions at
- // function addresses, to get to the "actual" function contents.
- // This allows us to identify two functions that are at different
- // addresses but actually resolve to the same code.
- //
- // @param target_function Pointer to a function.
- //
- // @return Either target_function (the input parameter), or if
- // target_function's body consists entirely of a JMP instruction,
- // the address it JMPs to (or more precisely, the address at the end
- // of a chain of JMPs).
- template <class T>
- static T ResolveTarget(T target_function) {
- return (T)ResolveTargetImpl((unsigned char*)target_function, NULL);
- }
-
- // Allocates a block of memory of size MAX_PREAMBLE_STUB_SIZE that is as
- // close (within 2GB) as possible to target. This is done to ensure that
- // we can perform a relative jump from target to a trampoline if the
- // replacement function is > +-2GB from target. This means that we only need
- // to patch 5 bytes in the target function.
- //
- // @param target Pointer to target function.
- //
- // @return Returns a block of memory of size MAX_PREAMBLE_STUB_SIZE that can
- // be used to store a function preamble block.
- static unsigned char* AllocPreambleBlockNear(void* target);
-
- // Frees a block allocated by AllocPreambleBlockNear.
- //
- // @param block Block that was returned by AllocPreambleBlockNear.
- static void FreePreambleBlock(unsigned char* block);
-
- private:
- friend class DeleteUnsignedCharArray;
-
- // Used to store data allocated for preamble stubs
- struct PreamblePage {
- unsigned int magic_;
- PreamblePage* next_;
- // This member points to a linked list of free blocks within the page
- // or NULL if at the end
- void* free_;
- };
-
- // In 64-bit mode, the replacement function must be within 2GB of the original
- // target in order to only require 5 bytes for the function patch. To meet
- // this requirement we're creating an allocator within this class to
- // allocate blocks that are within 2GB of a given target. This member is the
- // head of a linked list of pages used to allocate blocks that are within
- // 2GB of the target.
- static PreamblePage* preamble_pages_;
-
- // Page granularity
- static long granularity_;
-
- // Page size
- static long pagesize_;
-
- // Determines if the patcher has been initialized.
- static bool initialized_;
-
- // Used to initialize static members.
- static void Initialize();
-
- // Patches a function by overwriting its first few bytes with
- // a jump to a different function. This is similar to the RawPatch
- // function except that it uses the stub allocated by the caller
- // instead of allocating it.
- //
- // We call VirtualProtect to make the
- // target function writable at least for the duration of the call.
- //
- // @param target_function A pointer to the function that should be
- // patched.
- //
- // @param replacement_function A pointer to the function that should
- // replace the target function. The replacement function must have
- // exactly the same calling convention and parameters as the original
- // function.
- //
- // @param preamble_stub A pointer to a buffer where the preamble stub
- // should be copied. The size of the buffer should be sufficient to
- // hold the preamble bytes.
- //
- // @param stub_size Size in bytes of the buffer allocated for the
- // preamble_stub
- //
- // @param bytes_needed Pointer to a variable that receives the minimum
- // number of bytes required for the stub. Can be set to NULL if you're
- // not interested.
- //
- // @return An error code indicating the result of patching.
- static SideStepError RawPatchWithStubAndProtections(
- void* target_function,
- void* replacement_function,
- unsigned char* preamble_stub,
- unsigned long stub_size,
- unsigned long* bytes_needed);
-
- // A helper function used by RawPatchWithStubAndProtections -- it
- // does everything but the VirtualProtect work. Defined in
- // preamble_patcher_with_stub.cc.
- //
- // @param target_function A pointer to the function that should be
- // patched.
- //
- // @param replacement_function A pointer to the function that should
- // replace the target function. The replacement function must have
- // exactly the same calling convention and parameters as the original
- // function.
- //
- // @param preamble_stub A pointer to a buffer where the preamble stub
- // should be copied. The size of the buffer should be sufficient to
- // hold the preamble bytes.
- //
- // @param stub_size Size in bytes of the buffer allocated for the
- // preamble_stub
- //
- // @param bytes_needed Pointer to a variable that receives the minimum
- // number of bytes required for the stub. Can be set to NULL if you're
- // not interested.
- //
- // @return An error code indicating the result of patching.
- static SideStepError RawPatchWithStub(void* target_function,
- void* replacement_function,
- unsigned char* preamble_stub,
- unsigned long stub_size,
- unsigned long* bytes_needed);
-
-
- // A helper routine when patching, which follows jmp instructions at
- // function addresses, to get to the "actual" function contents.
- // This allows us to identify two functions that are at different
- // addresses but actually resolve to the same code.
- //
- // @param target_function Pointer to a function.
- //
- // @param stop_before If, when following JMP instructions from
- // target_function, we get to the address stop, we return
- // immediately, the address that jumps to stop_before.
- //
- // @param stop_before_trampoline When following JMP instructions from
- // target_function, stop before a trampoline is detected. See comment in
- // PreamblePatcher::RawPatchWithStub for more information. This parameter
- // has no effect in 32-bit mode.
- //
- // @return Either target_function (the input parameter), or if
- // target_function's body consists entirely of a JMP instruction,
- // the address it JMPs to (or more precisely, the address at the end
- // of a chain of JMPs).
- static void* ResolveTargetImpl(unsigned char* target_function,
- unsigned char* stop_before,
- bool stop_before_trampoline = false);
-
- // Helper routine that attempts to allocate a page as close (within 2GB)
- // as possible to target.
- //
- // @param target Pointer to target function.
- //
- // @return Returns an address that is within 2GB of target.
- static void* AllocPageNear(void* target);
-
- // Helper routine that determines if a target instruction is a short
- // conditional jump.
- //
- // @param target Pointer to instruction.
- //
- // @param instruction_size Size of the instruction in bytes.
- //
- // @return Returns true if the instruction is a short conditional jump.
- static bool IsShortConditionalJump(unsigned char* target,
- unsigned int instruction_size);
-
- static bool IsShortJump(unsigned char *target, unsigned int instruction_size);
-
- // Helper routine that determines if a target instruction is a near
- // conditional jump.
- //
- // @param target Pointer to instruction.
- //
- // @param instruction_size Size of the instruction in bytes.
- //
- // @return Returns true if the instruction is a near conditional jump.
- static bool IsNearConditionalJump(unsigned char* target,
- unsigned int instruction_size);
-
- // Helper routine that determines if a target instruction is a near
- // relative jump.
- //
- // @param target Pointer to instruction.
- //
- // @param instruction_size Size of the instruction in bytes.
- //
- // @return Returns true if the instruction is a near absolute jump.
- static bool IsNearRelativeJump(unsigned char* target,
- unsigned int instruction_size);
-
- // Helper routine that determines if a target instruction is a near
- // absolute call.
- //
- // @param target Pointer to instruction.
- //
- // @param instruction_size Size of the instruction in bytes.
- //
- // @return Returns true if the instruction is a near absolute call.
- static bool IsNearAbsoluteCall(unsigned char* target,
- unsigned int instruction_size);
-
- // Helper routine that determines if a target instruction is a near
- // absolute call.
- //
- // @param target Pointer to instruction.
- //
- // @param instruction_size Size of the instruction in bytes.
- //
- // @return Returns true if the instruction is a near absolute call.
- static bool IsNearRelativeCall(unsigned char* target,
- unsigned int instruction_size);
-
- // Helper routine that determines if a target instruction is a 64-bit MOV
- // that uses a RIP-relative displacement.
- //
- // @param target Pointer to instruction.
- //
- // @param instruction_size Size of the instruction in bytes.
- //
- // @return Returns true if the instruction is a MOV with displacement.
- static bool IsMovWithDisplacement(unsigned char* target,
- unsigned int instruction_size);
-
- // Helper routine that converts a short conditional jump instruction
- // to a near conditional jump in a target buffer. Note that the target
- // buffer must be within 2GB of the source for the near jump to work.
- //
- // A short conditional jump instruction is in the format:
- // 7x xx = Jcc rel8off
- //
- // @param source Pointer to instruction.
- //
- // @param instruction_size Size of the instruction.
- //
- // @param target Target buffer to write the new instruction.
- //
- // @param target_bytes Pointer to a buffer that contains the size
- // of the target instruction, in bytes.
- //
- // @param target_size Size of the target buffer.
- //
- // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error.
- static SideStepError PatchShortConditionalJump(unsigned char* source,
- unsigned int instruction_size,
- unsigned char* target,
- unsigned int* target_bytes,
- unsigned int target_size);
-
- static SideStepError PatchShortJump(unsigned char* source,
- unsigned int instruction_size,
- unsigned char* target,
- unsigned int* target_bytes,
- unsigned int target_size);
-
- // Helper routine that converts an instruction that will convert various
- // jump-like instructions to corresponding instructions in the target buffer.
- // What this routine does is fix up the relative offsets contained in jump
- // instructions to point back to the original target routine. Like with
- // PatchShortConditionalJump, the target buffer must be within 2GB of the
- // source.
- //
- // We currently handle the following instructions:
- //
- // E9 xx xx xx xx = JMP rel32off
- // 0F 8x xx xx xx xx = Jcc rel32off
- // FF /2 xx xx xx xx = CALL reg/mem32/mem64
- // E8 xx xx xx xx = CALL rel32off
- //
- // It should not be hard to update this function to support other
- // instructions that jump to relative targets.
- //
- // @param source Pointer to instruction.
- //
- // @param instruction_size Size of the instruction.
- //
- // @param target Target buffer to write the new instruction.
- //
- // @param target_bytes Pointer to a buffer that contains the size
- // of the target instruction, in bytes.
- //
- // @param target_size Size of the target buffer.
- //
- // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error.
- static SideStepError PatchNearJumpOrCall(unsigned char* source,
- unsigned int instruction_size,
- unsigned char* target,
- unsigned int* target_bytes,
- unsigned int target_size);
-
- // Helper routine that patches a 64-bit MOV instruction with a RIP-relative
- // displacement. The target buffer must be within 2GB of the source.
- //
- // 48 8B 0D XX XX XX XX = MOV rel32off
- //
- // @param source Pointer to instruction.
- //
- // @param instruction_size Size of the instruction.
- //
- // @param target Target buffer to write the new instruction.
- //
- // @param target_bytes Pointer to a buffer that contains the size
- // of the target instruction, in bytes.
- //
- // @param target_size Size of the target buffer.
- //
- // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error.
- static SideStepError PatchMovWithDisplacement(unsigned char* source,
- unsigned int instruction_size,
- unsigned char* target,
- unsigned int* target_bytes,
- unsigned int target_size);
-};
-
-}; // namespace sidestep
-
-#endif // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
diff --git a/src/third_party/gperftools-2.5/src/windows/preamble_patcher_test.cc b/src/third_party/gperftools-2.5/src/windows/preamble_patcher_test.cc
deleted file mode 100644
index e4605c6fb86..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/preamble_patcher_test.cc
+++ /dev/null
@@ -1,368 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* 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: Joi Sigurdsson
- * Author: Scott Francis
- *
- * Unit tests for PreamblePatcher
- */
-
-#include "config_for_unittests.h"
-#include "preamble_patcher.h"
-#include "mini_disassembler.h"
-#pragma warning(push)
-#pragma warning(disable:4553)
-#include "auto_testing_hook.h"
-#pragma warning(pop)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <tchar.h>
-
-// Turning off all optimizations for this file, since the official build's
-// "Whole program optimization" seems to cause the TestPatchUsingDynamicStub
-// test to crash with an access violation. We debugged this and found
-// that the optimized access a register that is changed by a call to the hook
-// function.
-#pragma optimize("", off)
-
-// A convenience macro to avoid a lot of casting in the tests.
-// I tried to make this a templated function, but windows complained:
-// error C2782: 'sidestep::SideStepError `anonymous-namespace'::Unpatch(T,T,T *)' : template parameter 'T' is ambiguous
-// could be 'int (int)'
-// or 'int (__cdecl *)(int)'
-// My life isn't long enough to try to figure out how to fix this.
-#define UNPATCH(target_function, replacement_function, original_function_stub) \
- sidestep::PreamblePatcher::Unpatch((void*)(target_function), \
- (void*)(replacement_function), \
- (void*)(original_function))
-
-namespace {
-
-// Function for testing - this is what we patch
-//
-// NOTE: Because of the way the compiler optimizes this function in
-// release builds, we need to use a different input value every time we
-// call it within a function, otherwise the compiler will just reuse the
-// last calculated incremented value.
-int __declspec(noinline) IncrementNumber(int i) {
-#ifdef _M_X64
- __int64 i2 = i + 1;
- return (int) i2;
-#else
- return i + 1;
-#endif
-}
-
-extern "C" int TooShortFunction(int);
-
-extern "C" int JumpShortCondFunction(int);
-
-extern "C" int JumpNearCondFunction(int);
-
-extern "C" int JumpAbsoluteFunction(int);
-
-extern "C" int CallNearRelativeFunction(int);
-
-typedef int (*IncrementingFunc)(int);
-IncrementingFunc original_function = NULL;
-
-int HookIncrementNumber(int i) {
- SIDESTEP_ASSERT(original_function != NULL);
- int incremented_once = original_function(i);
- return incremented_once + 1;
-}
-
-// For the AutoTestingHook test, we can't use original_function, because
-// all that is encapsulated.
-// This function "increments" by 10, just to set it apart from the other
-// functions.
-int __declspec(noinline) AutoHookIncrementNumber(int i) {
- return i + 10;
-}
-
-}; // namespace
-
-namespace sidestep {
-
-bool TestDisassembler() {
- unsigned int instruction_size = 0;
- sidestep::MiniDisassembler disassembler;
- void * target = reinterpret_cast<unsigned char *>(IncrementNumber);
- void * new_target = PreamblePatcher::ResolveTarget(target);
- if (target != new_target)
- target = new_target;
-
- while (1) {
- sidestep::InstructionType instructionType = disassembler.Disassemble(
- reinterpret_cast<unsigned char *>(target) + instruction_size,
- instruction_size);
- if (sidestep::IT_RETURN == instructionType) {
- return true;
- }
- }
-}
-
-bool TestPatchWithLongJump() {
- original_function = NULL;
- void *p = ::VirtualAlloc(reinterpret_cast<void *>(0x0000020000000000), 4096,
- MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- SIDESTEP_EXPECT_TRUE(p != NULL);
- memset(p, 0xcc, 4096);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(IncrementNumber,
- (IncrementingFunc) p,
- &original_function));
- SIDESTEP_ASSERT((*original_function)(1) == 2);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- UNPATCH(IncrementNumber,
- (IncrementingFunc)p,
- original_function));
- ::VirtualFree(p, 0, MEM_RELEASE);
- return true;
-}
-
-bool TestPatchWithPreambleShortCondJump() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(JumpShortCondFunction,
- HookIncrementNumber,
- &original_function));
- (*original_function)(1);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- UNPATCH(JumpShortCondFunction,
- (void*)HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool TestPatchWithPreambleNearRelativeCondJump() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(JumpNearCondFunction,
- HookIncrementNumber,
- &original_function));
- (*original_function)(0);
- (*original_function)(1);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- UNPATCH(JumpNearCondFunction,
- HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool TestPatchWithPreambleAbsoluteJump() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(JumpAbsoluteFunction,
- HookIncrementNumber,
- &original_function));
- (*original_function)(0);
- (*original_function)(1);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- UNPATCH(JumpAbsoluteFunction,
- HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool TestPatchWithPreambleNearRelativeCall() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(
- CallNearRelativeFunction,
- HookIncrementNumber,
- &original_function));
- (*original_function)(0);
- (*original_function)(1);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- UNPATCH(CallNearRelativeFunction,
- HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool TestPatchUsingDynamicStub() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(IncrementNumber,
- HookIncrementNumber,
- &original_function));
- SIDESTEP_EXPECT_TRUE(original_function);
- SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 4);
- SIDESTEP_EXPECT_TRUE(original_function(3) == 4);
-
- // Clearbox test to see that the function has been patched.
- sidestep::MiniDisassembler disassembler;
- unsigned int instruction_size = 0;
- SIDESTEP_EXPECT_TRUE(sidestep::IT_JUMP == disassembler.Disassemble(
- reinterpret_cast<unsigned char*>(IncrementNumber),
- instruction_size));
-
- // Since we patched IncrementNumber, its first statement is a
- // jmp to the hook function. So verify that we now can not patch
- // IncrementNumber because it starts with a jump.
-#if 0
- IncrementingFunc dummy = NULL;
- // TODO(joi@chromium.org): restore this test once flag is added to
- // disable JMP following
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_JUMP_INSTRUCTION ==
- sidestep::PreamblePatcher::Patch(IncrementNumber,
- HookIncrementNumber,
- &dummy));
-
- // This test disabled because code in preamble_patcher_with_stub.cc
- // asserts before returning the error code -- so there is no way
- // to get an error code here, in debug build.
- dummy = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_FUNCTION_TOO_SMALL ==
- sidestep::PreamblePatcher::Patch(TooShortFunction,
- HookIncrementNumber,
- &dummy));
-#endif
-
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- UNPATCH(IncrementNumber,
- HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool PatchThenUnpatch() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(IncrementNumber,
- HookIncrementNumber,
- &original_function));
- SIDESTEP_EXPECT_TRUE(original_function);
- SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 3);
- SIDESTEP_EXPECT_TRUE(original_function(2) == 3);
-
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- UNPATCH(IncrementNumber,
- HookIncrementNumber,
- original_function));
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
-
- return true;
-}
-
-bool AutoTestingHookTest() {
- SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
-
- // Inner scope, so we can test what happens when the AutoTestingHook
- // goes out of scope
- {
- AutoTestingHook hook = MakeTestingHook(IncrementNumber,
- AutoHookIncrementNumber);
- (void) hook;
- SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12);
- }
- SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
-
- return true;
-}
-
-bool AutoTestingHookInContainerTest() {
- SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
-
- // Inner scope, so we can test what happens when the AutoTestingHook
- // goes out of scope
- {
- AutoTestingHookHolder hook(MakeTestingHookHolder(IncrementNumber,
- AutoHookIncrementNumber));
- (void) hook;
- SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12);
- }
- SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
-
- return true;
-}
-
-bool TestPreambleAllocation() {
- __int64 diff = 0;
- void* p1 = reinterpret_cast<void*>(0x110000000);
- void* p2 = reinterpret_cast<void*>(0x810000000);
- unsigned char* b1 = PreamblePatcher::AllocPreambleBlockNear(p1);
- SIDESTEP_EXPECT_TRUE(b1 != NULL);
- diff = reinterpret_cast<__int64>(p1) - reinterpret_cast<__int64>(b1);
- // Ensure blocks are within 2GB
- SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN);
- unsigned char* b2 = PreamblePatcher::AllocPreambleBlockNear(p2);
- SIDESTEP_EXPECT_TRUE(b2 != NULL);
- diff = reinterpret_cast<__int64>(p2) - reinterpret_cast<__int64>(b2);
- SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN);
-
- // Ensure we're reusing free blocks
- unsigned char* b3 = b1;
- unsigned char* b4 = b2;
- PreamblePatcher::FreePreambleBlock(b1);
- PreamblePatcher::FreePreambleBlock(b2);
- b1 = PreamblePatcher::AllocPreambleBlockNear(p1);
- SIDESTEP_EXPECT_TRUE(b1 == b3);
- b2 = PreamblePatcher::AllocPreambleBlockNear(p2);
- SIDESTEP_EXPECT_TRUE(b2 == b4);
- PreamblePatcher::FreePreambleBlock(b1);
- PreamblePatcher::FreePreambleBlock(b2);
-
- return true;
-}
-
-bool UnitTests() {
- return TestPatchWithPreambleNearRelativeCall() &&
- TestPatchWithPreambleAbsoluteJump() &&
- TestPatchWithPreambleNearRelativeCondJump() &&
- TestPatchWithPreambleShortCondJump() &&
- TestDisassembler() && TestPatchWithLongJump() &&
- TestPatchUsingDynamicStub() && PatchThenUnpatch() &&
- AutoTestingHookTest() && AutoTestingHookInContainerTest() &&
- TestPreambleAllocation();
-}
-
-}; // namespace sidestep
-
-int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
- if (size == 0) // not even room for a \0?
- return -1; // not what C99 says to do, but what windows does
- str[size-1] = '\0';
- return _vsnprintf(str, size-1, format, ap);
-}
-
-int _tmain(int argc, _TCHAR* argv[])
-{
- bool ret = sidestep::UnitTests();
- printf("%s\n", ret ? "PASS" : "FAIL");
- return ret ? 0 : -1;
-}
-
-#pragma optimize("", on)
diff --git a/src/third_party/gperftools-2.5/src/windows/preamble_patcher_with_stub.cc b/src/third_party/gperftools-2.5/src/windows/preamble_patcher_with_stub.cc
deleted file mode 100644
index 23f9d3a0823..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/preamble_patcher_with_stub.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-/* Copyright (c) 2007, 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: Joi Sigurdsson
- * Author: Scott Francis
- *
- * Implementation of PreamblePatcher
- */
-
-#include "preamble_patcher.h"
-
-#include "mini_disassembler.h"
-
-// Definitions of assembly statements we need
-#define ASM_JMP32REL 0xE9
-#define ASM_INT3 0xCC
-#define ASM_NOP 0x90
-// X64 opcodes
-#define ASM_MOVRAX_IMM 0xB8
-#define ASM_REXW 0x48
-#define ASM_JMP 0xFF
-#define ASM_JMP_RAX 0xE0
-#define ASM_PUSH 0x68
-#define ASM_RET 0xC3
-
-namespace sidestep {
-
-SideStepError PreamblePatcher::RawPatchWithStub(
- void* target_function,
- void* replacement_function,
- unsigned char* preamble_stub,
- unsigned long stub_size,
- unsigned long* bytes_needed) {
- if ((NULL == target_function) ||
- (NULL == replacement_function) ||
- (NULL == preamble_stub)) {
- SIDESTEP_ASSERT(false &&
- "Invalid parameters - either pTargetFunction or "
- "pReplacementFunction or pPreambleStub were NULL.");
- return SIDESTEP_INVALID_PARAMETER;
- }
-
- // TODO(V7:joi) Siggi and I just had a discussion and decided that both
- // patching and unpatching are actually unsafe. We also discussed a
- // method of making it safe, which is to freeze all other threads in the
- // process, check their thread context to see if their eip is currently
- // inside the block of instructions we need to copy to the stub, and if so
- // wait a bit and try again, then unfreeze all threads once we've patched.
- // Not implementing this for now since we're only using SideStep for unit
- // testing, but if we ever use it for production code this is what we
- // should do.
- //
- // NOTE: Stoyan suggests we can write 8 or even 10 bytes atomically using
- // FPU instructions, and on newer processors we could use cmpxchg8b or
- // cmpxchg16b. So it might be possible to do the patching/unpatching
- // atomically and avoid having to freeze other threads. Note though, that
- // doing it atomically does not help if one of the other threads happens
- // to have its eip in the middle of the bytes you change while you change
- // them.
- unsigned char* target = reinterpret_cast<unsigned char*>(target_function);
- unsigned int required_trampoline_bytes = 0;
- const unsigned int kRequiredStubJumpBytes = 5;
- const unsigned int kRequiredTargetPatchBytes = 5;
-
- // Initialize the stub with INT3's just in case.
- if (stub_size) {
- memset(preamble_stub, 0xcc, stub_size);
- }
- if (kIs64BitBinary) {
- // In 64-bit mode JMP instructions are always relative to RIP. If the
- // replacement - target offset is > 2GB, we can't JMP to the replacement
- // function. In this case, we're going to use a trampoline - that is,
- // we're going to do a relative jump to a small chunk of code in the stub
- // that will then do the absolute jump to the replacement function. By
- // doing this, we only need to patch 5 bytes in the target function, as
- // opposed to patching 12 bytes if we were to do an absolute jump.
- //
- // Note that the first byte of the trampoline is a NOP instruction. This
- // is used as a trampoline signature that will be detected when unpatching
- // the function.
- //
- // jmp <trampoline>
- //
- // trampoline:
- // nop
- // mov rax, <replacement_function>
- // jmp rax
- //
- __int64 replacement_target_offset = reinterpret_cast<__int64>(
- replacement_function) - reinterpret_cast<__int64>(target) - 5;
- if (replacement_target_offset > INT_MAX
- || replacement_target_offset < INT_MIN) {
- // The stub needs to be within 2GB of the target for the trampoline to
- // work!
- __int64 trampoline_offset = reinterpret_cast<__int64>(preamble_stub)
- - reinterpret_cast<__int64>(target) - 5;
- if (trampoline_offset > INT_MAX || trampoline_offset < INT_MIN) {
- // We're screwed.
- SIDESTEP_ASSERT(false
- && "Preamble stub is too far from target to patch.");
- return SIDESTEP_UNEXPECTED;
- }
- required_trampoline_bytes = 13;
- }
- }
-
- // Let's disassemble the preamble of the target function to see if we can
- // patch, and to see how much of the preamble we need to take. We need 5
- // bytes for our jmp instruction, so let's find the minimum number of
- // instructions to get 5 bytes.
- MiniDisassembler disassembler;
- unsigned int preamble_bytes = 0;
- unsigned int stub_bytes = 0;
- while (preamble_bytes < kRequiredTargetPatchBytes) {
- unsigned int cur_bytes = 0;
- InstructionType instruction_type =
- disassembler.Disassemble(target + preamble_bytes, cur_bytes);
- if (IT_JUMP == instruction_type) {
- unsigned int jump_bytes = 0;
- SideStepError jump_ret = SIDESTEP_JUMP_INSTRUCTION;
- if (IsShortConditionalJump(target + preamble_bytes, cur_bytes)) {
- jump_ret = PatchShortConditionalJump(target + preamble_bytes, cur_bytes,
- preamble_stub + stub_bytes,
- &jump_bytes,
- stub_size - stub_bytes);
- } else if (IsShortJump(target + preamble_bytes, cur_bytes)) {
- jump_ret = PatchShortJump(target + preamble_bytes, cur_bytes,
- preamble_stub + stub_bytes,
- &jump_bytes,
- stub_size - stub_bytes);
- } else if (IsNearConditionalJump(target + preamble_bytes, cur_bytes) ||
- IsNearRelativeJump(target + preamble_bytes, cur_bytes) ||
- IsNearAbsoluteCall(target + preamble_bytes, cur_bytes) ||
- IsNearRelativeCall(target + preamble_bytes, cur_bytes)) {
- jump_ret = PatchNearJumpOrCall(target + preamble_bytes, cur_bytes,
- preamble_stub + stub_bytes, &jump_bytes,
- stub_size - stub_bytes);
- }
- if (jump_ret != SIDESTEP_SUCCESS) {
- SIDESTEP_ASSERT(false &&
- "Unable to patch because there is an unhandled branch "
- "instruction in the initial preamble bytes.");
- return SIDESTEP_JUMP_INSTRUCTION;
- }
- stub_bytes += jump_bytes;
- } else if (IT_RETURN == instruction_type) {
- SIDESTEP_ASSERT(false &&
- "Unable to patch because function is too short");
- return SIDESTEP_FUNCTION_TOO_SMALL;
- } else if (IT_GENERIC == instruction_type) {
- if (IsMovWithDisplacement(target + preamble_bytes, cur_bytes)) {
- unsigned int mov_bytes = 0;
- if (PatchMovWithDisplacement(target + preamble_bytes, cur_bytes,
- preamble_stub + stub_bytes, &mov_bytes,
- stub_size - stub_bytes)
- != SIDESTEP_SUCCESS) {
- return SIDESTEP_UNSUPPORTED_INSTRUCTION;
- }
- stub_bytes += mov_bytes;
- } else {
- memcpy(reinterpret_cast<void*>(preamble_stub + stub_bytes),
- reinterpret_cast<void*>(target + preamble_bytes), cur_bytes);
- stub_bytes += cur_bytes;
- }
- } else {
- SIDESTEP_ASSERT(false &&
- "Disassembler encountered unsupported instruction "
- "(either unused or unknown");
- return SIDESTEP_UNSUPPORTED_INSTRUCTION;
- }
- preamble_bytes += cur_bytes;
- }
-
- if (NULL != bytes_needed)
- *bytes_needed = stub_bytes + kRequiredStubJumpBytes
- + required_trampoline_bytes;
-
- // Inv: cbPreamble is the number of bytes (at least 5) that we need to take
- // from the preamble to have whole instructions that are 5 bytes or more
- // in size total. The size of the stub required is cbPreamble +
- // kRequiredStubJumpBytes (5) + required_trampoline_bytes (0 or 13)
- if (stub_bytes + kRequiredStubJumpBytes + required_trampoline_bytes
- > stub_size) {
- SIDESTEP_ASSERT(false);
- return SIDESTEP_INSUFFICIENT_BUFFER;
- }
-
- // Now, make a jmp instruction to the rest of the target function (minus the
- // preamble bytes we moved into the stub) and copy it into our preamble-stub.
- // find address to jump to, relative to next address after jmp instruction
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4244)
-#endif
- int relative_offset_to_target_rest
- = ((reinterpret_cast<unsigned char*>(target) + preamble_bytes) -
- (preamble_stub + stub_bytes + kRequiredStubJumpBytes));
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- // jmp (Jump near, relative, displacement relative to next instruction)
- preamble_stub[stub_bytes] = ASM_JMP32REL;
- // copy the address
- memcpy(reinterpret_cast<void*>(preamble_stub + stub_bytes + 1),
- reinterpret_cast<void*>(&relative_offset_to_target_rest), 4);
-
- if (kIs64BitBinary && required_trampoline_bytes != 0) {
- // Construct the trampoline
- unsigned int trampoline_pos = stub_bytes + kRequiredStubJumpBytes;
- preamble_stub[trampoline_pos] = ASM_NOP;
- preamble_stub[trampoline_pos + 1] = ASM_REXW;
- preamble_stub[trampoline_pos + 2] = ASM_MOVRAX_IMM;
- memcpy(reinterpret_cast<void*>(preamble_stub + trampoline_pos + 3),
- reinterpret_cast<void*>(&replacement_function),
- sizeof(void *));
- preamble_stub[trampoline_pos + 11] = ASM_JMP;
- preamble_stub[trampoline_pos + 12] = ASM_JMP_RAX;
-
- // Now update replacement_function to point to the trampoline
- replacement_function = preamble_stub + trampoline_pos;
- }
-
- // Inv: preamble_stub points to assembly code that will execute the
- // original function by first executing the first cbPreamble bytes of the
- // preamble, then jumping to the rest of the function.
-
- // Overwrite the first 5 bytes of the target function with a jump to our
- // replacement function.
- // (Jump near, relative, displacement relative to next instruction)
- target[0] = ASM_JMP32REL;
-
- // Find offset from instruction after jmp, to the replacement function.
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4244)
-#endif
- int offset_to_replacement_function =
- reinterpret_cast<unsigned char*>(replacement_function) -
- reinterpret_cast<unsigned char*>(target) - 5;
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- // complete the jmp instruction
- memcpy(reinterpret_cast<void*>(target + 1),
- reinterpret_cast<void*>(&offset_to_replacement_function), 4);
-
- // Set any remaining bytes that were moved to the preamble-stub to INT3 so
- // as not to cause confusion (otherwise you might see some strange
- // instructions if you look at the disassembly, or even invalid
- // instructions). Also, by doing this, we will break into the debugger if
- // some code calls into this portion of the code. If this happens, it
- // means that this function cannot be patched using this patcher without
- // further thought.
- if (preamble_bytes > kRequiredTargetPatchBytes) {
- memset(reinterpret_cast<void*>(target + kRequiredTargetPatchBytes),
- ASM_INT3, preamble_bytes - kRequiredTargetPatchBytes);
- }
-
- // Inv: The memory pointed to by target_function now points to a relative
- // jump instruction that jumps over to the preamble_stub. The preamble
- // stub contains the first stub_size bytes of the original target
- // function's preamble code, followed by a relative jump back to the next
- // instruction after the first cbPreamble bytes.
- //
- // In 64-bit mode the memory pointed to by target_function *may* point to a
- // relative jump instruction that jumps to a trampoline which will then
- // perform an absolute jump to the replacement function. The preamble stub
- // still contains the original target function's preamble code, followed by a
- // jump back to the instructions after the first preamble bytes.
- //
- return SIDESTEP_SUCCESS;
-}
-
-}; // namespace sidestep
diff --git a/src/third_party/gperftools-2.5/src/windows/shortproc.asm b/src/third_party/gperftools-2.5/src/windows/shortproc.asm
deleted file mode 100644
index 7e8e3d78395..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/shortproc.asm
+++ /dev/null
@@ -1,169 +0,0 @@
-; 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: Scott Francis
-;
-; Unit tests for PreamblePatcher
-
-.MODEL small
-
-.CODE
-
-TooShortFunction PROC
- ret
-TooShortFunction ENDP
-
-JumpShortCondFunction PROC
- test cl, 1
- jnz jumpspot
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
- int 3
-jumpspot:
- nop
- nop
- nop
- nop
- mov rax, 1
- ret
-JumpShortCondFunction ENDP
-
-JumpNearCondFunction PROC
- test cl, 1
- jnz jumpspot
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
-jumpspot:
- nop
- nop
- mov rax, 1
- ret
-JumpNearCondFunction ENDP
-
-JumpAbsoluteFunction PROC
- test cl, 1
- jmp jumpspot
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
-jumpspot:
- nop
- nop
- mov rax, 1
- ret
-JumpAbsoluteFunction ENDP
-
-CallNearRelativeFunction PROC
- test cl, 1
- call TooShortFunction
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- mov rdx, 0ffff1111H
- nop
- nop
- nop
- ret
-CallNearRelativeFunction ENDP
-
-END
diff --git a/src/third_party/gperftools-2.5/src/windows/system-alloc.cc b/src/third_party/gperftools-2.5/src/windows/system-alloc.cc
deleted file mode 100644
index 9537745b86f..00000000000
--- a/src/third_party/gperftools-2.5/src/windows/system-alloc.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright (c) 2013, 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: Petr Hosek
-
-#ifndef _WIN32
-# error You should only be including windows/system-alloc.cc in a windows environment!
-#endif
-
-#include <config.h>
-#include <windows.h>
-#include <algorithm> // std::min
-#include <gperftools/malloc_extension.h>
-#include "base/logging.h"
-#include "base/spinlock.h"
-#include "internal_logging.h"
-#include "system-alloc.h"
-
-static SpinLock spinlock(SpinLock::LINKER_INITIALIZED);
-
-// The current system allocator declaration
-SysAllocator* sys_alloc = NULL;
-// Number of bytes taken from system.
-size_t TCMalloc_SystemTaken = 0;
-
-class VirtualSysAllocator : public SysAllocator {
-public:
- VirtualSysAllocator() : SysAllocator() {
- }
- void* Alloc(size_t size, size_t *actual_size, size_t alignment);
-};
-static char virtual_space[sizeof(VirtualSysAllocator)];
-
-// This is mostly like MmapSysAllocator::Alloc, except it does these weird
-// munmap's in the middle of the page, which is forbidden in windows.
-void* VirtualSysAllocator::Alloc(size_t size, size_t *actual_size,
- size_t alignment) {
- // Align on the pagesize boundary
- const int pagesize = getpagesize();
- if (alignment < pagesize) alignment = pagesize;
- size = ((size + alignment - 1) / alignment) * alignment;
-
- // Report the total number of bytes the OS actually delivered. This might be
- // greater than |size| because of alignment concerns. The full size is
- // necessary so that adjacent spans can be coalesced.
- // TODO(antonm): proper processing of alignments
- // in actual_size and decommitting.
- if (actual_size) {
- *actual_size = size;
- }
-
- // We currently do not support alignments larger than the pagesize or
- // alignments that are not multiples of the pagesize after being floored.
- // If this ability is needed it can be done by the caller (assuming it knows
- // the page size).
- assert(alignment <= pagesize);
-
- void* result = VirtualAlloc(0, size,
- MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
- if (result == NULL)
- return NULL;
-
- // If the result is not aligned memory fragmentation will result which can
- // lead to pathological memory use.
- assert((reinterpret_cast<uintptr_t>(result) & (alignment - 1)) == 0);
-
- return result;
-}
-
-#ifdef _MSC_VER
-
-extern "C" SysAllocator* tc_get_sysalloc_override(SysAllocator *def);
-extern "C" SysAllocator* tc_get_sysalloc_default(SysAllocator *def)
-{
- return def;
-}
-
-#if defined(_M_IX86)
-#pragma comment(linker, "/alternatename:_tc_get_sysalloc_override=_tc_get_sysalloc_default")
-#elif defined(_M_X64)
-#pragma comment(linker, "/alternatename:tc_get_sysalloc_override=tc_get_sysalloc_default")
-#endif
-
-#else // !_MSC_VER
-
-extern "C" ATTRIBUTE_NOINLINE
-SysAllocator* tc_get_sysalloc_override(SysAllocator *def)
-{
- return def;
-}
-
-#endif
-
-static bool system_alloc_inited = false;
-void InitSystemAllocators(void) {
- VirtualSysAllocator *alloc = new (virtual_space) VirtualSysAllocator();
- sys_alloc = tc_get_sysalloc_override(alloc);
-}
-
-extern PERFTOOLS_DLL_DECL
-void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
- size_t alignment) {
- SpinLockHolder lock_holder(&spinlock);
-
- if (!system_alloc_inited) {
- InitSystemAllocators();
- system_alloc_inited = true;
- }
-
- void* result = sys_alloc->Alloc(size, actual_size, alignment);
- if (result != NULL) {
- if (actual_size) {
- TCMalloc_SystemTaken += *actual_size;
- } else {
- TCMalloc_SystemTaken += size;
- }
- }
- return result;
-}
-
-extern PERFTOOLS_DLL_DECL
-bool TCMalloc_SystemRelease(void* start, size_t length) {
- if (VirtualFree(start, length, MEM_DECOMMIT))
- return true;
-
- // The decommit may fail if the memory region consists of allocations
- // from more than one call to VirtualAlloc. In this case, fall back to
- // using VirtualQuery to retrieve the allocation boundaries and decommit
- // them each individually.
-
- char* ptr = static_cast<char*>(start);
- char* end = ptr + length;
- MEMORY_BASIC_INFORMATION info;
- while (ptr < end) {
- size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
- assert(resultSize == sizeof(info));
- size_t decommitSize = std::min<size_t>(info.RegionSize, end - ptr);
- BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT);
- assert(success == TRUE);
- ptr += decommitSize;
- }
-
- return true;
-}
-
-extern PERFTOOLS_DLL_DECL
-void TCMalloc_SystemCommit(void* start, size_t length) {
- if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start)
- return;
-
- // The commit may fail if the memory region consists of allocations
- // from more than one call to VirtualAlloc. In this case, fall back to
- // using VirtualQuery to retrieve the allocation boundaries and commit them
- // each individually.
-
- char* ptr = static_cast<char*>(start);
- char* end = ptr + length;
- MEMORY_BASIC_INFORMATION info;
- while (ptr < end) {
- size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
- assert(resultSize == sizeof(info));
-
- size_t commitSize = std::min<size_t>(info.RegionSize, end - ptr);
- void* newAddress = VirtualAlloc(ptr, commitSize, MEM_COMMIT,
- PAGE_READWRITE);
- assert(newAddress == ptr);
- ptr += commitSize;
- }
-}
-
-bool RegisterSystemAllocator(SysAllocator *allocator, int priority) {
- return false; // we don't allow registration on windows, right now
-}
-
-void DumpSystemAllocatorStats(TCMalloc_Printer* printer) {
- // We don't dump stats on windows, right now
-}