diff options
author | thakis <thakis@chromium.org> | 2015-09-11 06:50:59 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-11 13:51:44 +0000 |
commit | 5747a19cad8feb463125f3c80376d3c535f25523 (patch) | |
tree | 1bc808412d73082fa5b8f6ede63c197eeb5653aa | |
parent | 8ee79634c84a8a26ec2993163cc1d606f656986b (diff) | |
download | chromium_src-5747a19cad8feb463125f3c80376d3c535f25523.zip chromium_src-5747a19cad8feb463125f3c80376d3c535f25523.tar.gz chromium_src-5747a19cad8feb463125f3c80376d3c535f25523.tar.bz2 |
Remove clang type profiler and deep memory profiler.
Looks like it's no longer functional and unused.
BUG=490464
TBR=jochen
Review URL: https://codereview.chromium.org/1331973002
Cr-Commit-Position: refs/heads/master@{#348392}
28 files changed, 10 insertions, 2621 deletions
diff --git a/base/BUILD.gn b/base/BUILD.gn index 8058c77..48409f9 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -64,8 +64,6 @@ component("base") { sources = [ "allocator/allocator_extension.cc", "allocator/allocator_extension.h", - "allocator/type_profiler_control.cc", - "allocator/type_profiler_control.h", "android/animation_frame_time_histogram.cc", "android/animation_frame_time_histogram.h", "android/apk_assets.cc", @@ -728,8 +726,6 @@ component("base") { set_sources_assignment_filter(sources_assignment_filter) sources -= [ - "allocator/type_profiler_control.cc", - "allocator/type_profiler_control.h", "async_socket_io_handler_posix.cc", "cpu.cc", "files/file_enumerator_posix.cc", diff --git a/base/allocator/BUILD.gn b/base/allocator/BUILD.gn index b6b7fc2..c12431b 100644 --- a/base/allocator/BUILD.gn +++ b/base/allocator/BUILD.gn @@ -100,7 +100,7 @@ if (use_allocator == "tcmalloc") { check_includes = false sources = [ - # Generated for our configuration from tcmalloc"s build + # Generated for our configuration from tcmalloc's build # and checked in. "$tcmalloc_dir/src/config.h", "$tcmalloc_dir/src/config_android.h", @@ -151,8 +151,6 @@ if (use_allocator == "tcmalloc") { # #included by debugallocation_shim.cc #"$tcmalloc_dir/src/debugallocation.cc", - "$tcmalloc_dir/src/deep-heap-profile.cc", - "$tcmalloc_dir/src/deep-heap-profile.h", "$tcmalloc_dir/src/free_list.cc", "$tcmalloc_dir/src/free_list.h", "$tcmalloc_dir/src/heap-profile-table.cc", diff --git a/base/allocator/allocator.gyp b/base/allocator/allocator.gyp index 7cd9b64..ae93e9e 100644 --- a/base/allocator/allocator.gyp +++ b/base/allocator/allocator.gyp @@ -153,8 +153,6 @@ '<(tcmalloc_dir)/src/common.cc', '<(tcmalloc_dir)/src/common.h', '<(tcmalloc_dir)/src/debugallocation.cc', - '<(tcmalloc_dir)/src/deep-heap-profile.cc', - '<(tcmalloc_dir)/src/deep-heap-profile.h', '<(tcmalloc_dir)/src/free_list.cc', '<(tcmalloc_dir)/src/free_list.h', '<(tcmalloc_dir)/src/getpc.h', @@ -296,19 +294,6 @@ '../..', ], }], - ['OS=="linux" and clang_type_profiler==1', { - 'dependencies': [ - 'type_profiler_tcmalloc', - ], - # It is undoing dependencies and cflags_cc for type_profiler which - # build/common.gypi injects into all targets. - 'dependencies!': [ - 'type_profiler', - ], - 'cflags_cc!': [ - '-fintercept-allocation-functions', - ], - }], ['OS=="win" and component!="shared_library"', { 'dependencies': [ 'libcmt', @@ -382,18 +367,6 @@ 'include_dirs': [ '../../' ], - 'conditions': [ - ['OS=="linux" and clang_type_profiler==1', { - # It is undoing dependencies and cflags_cc for type_profiler which - # build/common.gypi injects into all targets. - 'dependencies!': [ - 'type_profiler', - ], - 'cflags_cc!': [ - '-fintercept-allocation-functions', - ], - }], - ], }, ], 'conditions': [ @@ -462,93 +435,6 @@ }, ], }], - ['OS=="linux" and clang_type_profiler==1', { - # Some targets in this section undo dependencies and cflags_cc for - # type_profiler which build/common.gypi injects into all targets. - 'targets': [ - { - 'target_name': 'type_profiler', - 'type': 'static_library', - 'dependencies!': [ - 'type_profiler', - ], - 'cflags_cc!': [ - '-fintercept-allocation-functions', - ], - 'include_dirs': [ - '../..', - ], - 'sources': [ - 'type_profiler.cc', - 'type_profiler.h', - 'type_profiler_control.h', - ], - 'toolsets': ['host', 'target'], - }, - { - 'target_name': 'type_profiler_tcmalloc', - 'type': 'static_library', - 'dependencies!': [ - 'type_profiler', - ], - 'cflags_cc!': [ - '-fintercept-allocation-functions', - ], - 'include_dirs': [ - '<(tcmalloc_dir)/src', - '../..', - ], - 'sources': [ - '<(tcmalloc_dir)/src/gperftools/type_profiler_map.h', - '<(tcmalloc_dir)/src/type_profiler_map.cc', - 'type_profiler_tcmalloc.cc', - 'type_profiler_tcmalloc.h', - ], - }, - { - 'target_name': 'type_profiler_unittests', - 'type': 'executable', - 'dependencies': [ - '../../testing/gtest.gyp:gtest', - '../base.gyp:base', - 'allocator', - 'type_profiler_tcmalloc', - ], - 'include_dirs': [ - '../..', - ], - 'sources': [ - 'type_profiler_control.cc', - 'type_profiler_control.h', - 'type_profiler_unittest.cc', - ], - }, - { - 'target_name': 'type_profiler_map_unittests', - 'type': 'executable', - 'dependencies': [ - '../../testing/gtest.gyp:gtest', - '../base.gyp:base', - 'allocator', - ], - 'dependencies!': [ - 'type_profiler', - ], - 'cflags_cc!': [ - '-fintercept-allocation-functions', - ], - 'include_dirs': [ - '<(tcmalloc_dir)/src', - '../..', - ], - 'sources': [ - '<(tcmalloc_dir)/src/gperftools/type_profiler_map.h', - '<(tcmalloc_dir)/src/type_profiler_map.cc', - 'type_profiler_map_unittest.cc', - ], - }, - ], - }], ['use_allocator=="tcmalloc"', { 'targets': [ { diff --git a/base/allocator/type_profiler.cc b/base/allocator/type_profiler.cc deleted file mode 100644 index 635fbcf..0000000 --- a/base/allocator/type_profiler.cc +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#if defined(TYPE_PROFILING) - -#include "base/allocator/type_profiler.h" - -#include <assert.h> - -namespace { - -void* NopIntercept(void* ptr, size_t size, const std::type_info& type) { - return ptr; -} - -base::type_profiler::InterceptFunction* g_new_intercept = NopIntercept; -base::type_profiler::InterceptFunction* g_delete_intercept = NopIntercept; - -} - -void* __op_new_intercept__(void* ptr, - size_t size, - const std::type_info& type) { - return g_new_intercept(ptr, size, type); -} - -void* __op_delete_intercept__(void* ptr, - size_t size, - const std::type_info& type) { - return g_delete_intercept(ptr, size, type); -} - -namespace base { -namespace type_profiler { - -// static -void InterceptFunctions::SetFunctions(InterceptFunction* new_intercept, - InterceptFunction* delete_intercept) { - // Don't use DCHECK, as this file is injected into targets - // that do not and should not depend on base/base.gyp:base - assert(g_new_intercept == NopIntercept); - assert(g_delete_intercept == NopIntercept); - - g_new_intercept = new_intercept; - g_delete_intercept = delete_intercept; -} - -// static -void InterceptFunctions::ResetFunctions() { - g_new_intercept = NopIntercept; - g_delete_intercept = NopIntercept; -} - -// static -bool InterceptFunctions::IsAvailable() { - return g_new_intercept != NopIntercept || g_delete_intercept != NopIntercept; -} - -} // namespace type_profiler -} // namespace base - -#endif // defined(TYPE_PROFILING) diff --git a/base/allocator/type_profiler.h b/base/allocator/type_profiler.h deleted file mode 100644 index 86b5711..0000000 --- a/base/allocator/type_profiler.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_ALLOCATOR_TYPE_PROFILER_H_ -#define BASE_ALLOCATOR_TYPE_PROFILER_H_ - -#if defined(TYPE_PROFILING) - -#include <stddef.h> // for size_t -#include <typeinfo> // for std::typeinfo - -namespace base { -namespace type_profiler { - -typedef void* InterceptFunction(void*, size_t, const std::type_info&); - -class InterceptFunctions { - public: - // It must be called only once in a process while it is in single-thread. - // For now, ContentMainRunnerImpl::Initialize is the only supposed caller - // of this function except for single-threaded unit tests. - static void SetFunctions(InterceptFunction* new_intercept, - InterceptFunction* delete_intercept); - - private: - friend class TypeProfilerTest; - - // These functions are not thread safe. - // They must be used only from single-threaded unit tests. - static void ResetFunctions(); - static bool IsAvailable(); -}; - -} // namespace type_profiler -} // namespace base - -#endif // defined(TYPE_PROFILING) - -#endif // BASE_ALLOCATOR_TYPE_PROFILER_H_ diff --git a/base/allocator/type_profiler_control.cc b/base/allocator/type_profiler_control.cc deleted file mode 100644 index 6be7984..0000000 --- a/base/allocator/type_profiler_control.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/allocator/type_profiler_control.h" - -namespace base { -namespace type_profiler { - -namespace { - -#if defined(TYPE_PROFILING) -const bool kTypeProfilingEnabled = true; -#else -const bool kTypeProfilingEnabled = false; -#endif - -bool g_enable_intercept = kTypeProfilingEnabled; - -} // namespace - -// static -void Controller::Stop() { - g_enable_intercept = false; -} - -// static -bool Controller::IsProfiling() { - return kTypeProfilingEnabled && g_enable_intercept; -} - -// static -void Controller::Restart() { - g_enable_intercept = kTypeProfilingEnabled; -} - -} // namespace type_profiler -} // namespace base diff --git a/base/allocator/type_profiler_control.h b/base/allocator/type_profiler_control.h deleted file mode 100644 index 17cf5b6..0000000 --- a/base/allocator/type_profiler_control.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_ALLOCATOR_TYPE_PROFILER_CONTROL_H_ -#define BASE_ALLOCATOR_TYPE_PROFILER_CONTROL_H_ - -#include "base/gtest_prod_util.h" - -namespace base { -namespace type_profiler { - -class Controller { - public: - static void Stop(); - static bool IsProfiling(); - - private: - FRIEND_TEST_ALL_PREFIXES(TypeProfilerTest, - TestProfileNewWithoutProfiledDelete); - - // It must be used only from allowed unit tests. The following is only - // allowed for use in unit tests. Profiling should never be restarted in - // regular use. - static void Restart(); -}; - -} // namespace type_profiler -} // namespace base - -#endif // BASE_ALLOCATOR_TYPE_PROFILER_CONTROL_H_ diff --git a/base/allocator/type_profiler_map_unittest.cc b/base/allocator/type_profiler_map_unittest.cc deleted file mode 100644 index 514ec16..0000000 --- a/base/allocator/type_profiler_map_unittest.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is a unittest set for type_profiler_map in third_party/tcmalloc. It is -// independent from other tests and executed manually like allocator_unittests -// since type_profiler_map is a singleton (like TCMalloc's heap-profiler), and -// it requires RTTI and different compiling/linking options from others. - -#if defined(TYPE_PROFILING) - -#include "base/memory/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h" - -namespace base { -namespace type_profiler { - -static const void* const g_const_null = static_cast<const void*>(NULL); - -TEST(TypeProfilerMapTest, NormalOperation) { - // Allocate an object just to get a valid address. - // This 'new' is not profiled by type_profiler. - scoped_ptr<int> dummy(new int(48)); - const std::type_info* type; - - type = LookupType(dummy.get()); - EXPECT_EQ(g_const_null, type); - - InsertType(dummy.get(), 12, typeid(int)); - type = LookupType(dummy.get()); - ASSERT_NE(g_const_null, type); - EXPECT_STREQ(typeid(int).name(), type->name()); - - EraseType(dummy.get()); - type = LookupType(dummy.get()); - EXPECT_EQ(g_const_null, type); -} - -TEST(TypeProfilerMapTest, EraseWithoutInsert) { - scoped_ptr<int> dummy(new int(48)); - const std::type_info* type; - - for (int i = 0; i < 10; ++i) { - EraseType(dummy.get()); - type = LookupType(dummy.get()); - EXPECT_EQ(g_const_null, type); - } -} - -TEST(TypeProfilerMapTest, InsertThenMultipleErase) { - scoped_ptr<int> dummy(new int(48)); - const std::type_info* type; - - InsertType(dummy.get(), 12, typeid(int)); - type = LookupType(dummy.get()); - ASSERT_NE(g_const_null, type); - EXPECT_STREQ(typeid(int).name(), type->name()); - - for (int i = 0; i < 10; ++i) { - EraseType(dummy.get()); - type = LookupType(dummy.get()); - EXPECT_EQ(g_const_null, type); - } -} - -TEST(TypeProfilerMapTest, MultipleInsertWithoutErase) { - scoped_ptr<int> dummy(new int(48)); - const std::type_info* type; - - InsertType(dummy.get(), 12, typeid(int)); - type = LookupType(dummy.get()); - ASSERT_NE(g_const_null, type); - EXPECT_STREQ(typeid(int).name(), type->name()); - - InsertType(dummy.get(), 5, typeid(char)); - type = LookupType(dummy.get()); - ASSERT_NE(g_const_null, type); - EXPECT_STREQ(typeid(char).name(), type->name()); - - InsertType(dummy.get(), 129, typeid(long)); - type = LookupType(dummy.get()); - ASSERT_NE(g_const_null, type); - EXPECT_STREQ(typeid(long).name(), type->name()); - - EraseType(dummy.get()); - type = LookupType(dummy.get()); - EXPECT_EQ(g_const_null, type); -} - -} // namespace type_profiler -} // namespace base - -#endif // defined(TYPE_PROFILING) - -int main(int argc, char** argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/base/allocator/type_profiler_tcmalloc.cc b/base/allocator/type_profiler_tcmalloc.cc deleted file mode 100644 index e5e10e0..0000000 --- a/base/allocator/type_profiler_tcmalloc.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#if defined(TYPE_PROFILING) - -#include "base/allocator/type_profiler_tcmalloc.h" - -#include "base/allocator/type_profiler_control.h" -#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" -#include "third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h" - -namespace base { -namespace type_profiler { - -void* NewInterceptForTCMalloc(void* ptr, - size_t size, - const std::type_info& type) { - if (Controller::IsProfiling()) - InsertType(ptr, size, type); - - return ptr; -} - -void* DeleteInterceptForTCMalloc(void* ptr, - size_t size, - const std::type_info& type) { - if (Controller::IsProfiling()) - EraseType(ptr); - - return ptr; -} - -} // namespace type_profiler -} // namespace base - -#endif // defined(TYPE_PROFILING) diff --git a/base/allocator/type_profiler_tcmalloc.h b/base/allocator/type_profiler_tcmalloc.h deleted file mode 100644 index ac55995..0000000 --- a/base/allocator/type_profiler_tcmalloc.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_ALLOCATOR_TYPE_PROFILER_TCMALLOC_H_ -#define BASE_ALLOCATOR_TYPE_PROFILER_TCMALLOC_H_ - -#if defined(TYPE_PROFILING) - -#include <cstddef> // for size_t -#include <typeinfo> // for std::type_info - -namespace base { -namespace type_profiler { - -void* NewInterceptForTCMalloc(void* ptr, - size_t size, - const std::type_info& type); - -void* DeleteInterceptForTCMalloc(void* ptr, - size_t size, - const std::type_info& type); - -} // namespace type_profiler -} // namespace base - -#endif // defined(TYPE_PROFILING) - -#endif // BASE_ALLOCATOR_TYPE_PROFILER_TCMALLOC_H_ diff --git a/base/allocator/type_profiler_unittest.cc b/base/allocator/type_profiler_unittest.cc deleted file mode 100644 index 3d7369c38..0000000 --- a/base/allocator/type_profiler_unittest.cc +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is a unittest set for type_profiler. It is independent from other -// tests and executed manually like allocator_unittests since type_profiler_map -// used in type_profiler is a singleton (like TCMalloc's heap-profiler), and -// it requires RTTI and different compiling/linking options from others -// -// It tests that the profiler doesn't fail in suspicous cases. For example, -// 'new' is not profiled, but 'delete' for the created object is profiled. - -#if defined(TYPE_PROFILING) - -#include "base/allocator/type_profiler.h" -#include "base/allocator/type_profiler_control.h" -#include "base/allocator/type_profiler_tcmalloc.h" -#include "base/basictypes.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h" - -namespace base { -namespace type_profiler { - -class TypeProfilerTest : public testing::Test { - public: - TypeProfilerTest() {} - - void SetInterceptFunctions() { - InterceptFunctions::SetFunctions(NewInterceptForTCMalloc, - DeleteInterceptForTCMalloc); - } - - void ResetInterceptFunctions() { - InterceptFunctions::ResetFunctions(); - } - - void SetUp() { - SetInterceptFunctions(); - } - - void TearDown() { - ResetInterceptFunctions(); - } - - protected: - static const size_t kDummyArraySize; - static const void* const kConstNull; - - private: - DISALLOW_COPY_AND_ASSIGN(TypeProfilerTest); -}; - -const size_t TypeProfilerTest::kDummyArraySize = 10; -const void* const TypeProfilerTest::kConstNull = static_cast<const void*>(NULL); - -TEST_F(TypeProfilerTest, TestNormalProfiling) { - int* dummy = new int(48); - const std::type_info* type; - - type = LookupType(dummy); - ASSERT_NE(kConstNull, type); - EXPECT_STREQ(typeid(int).name(), type->name()); - delete dummy; - - type = LookupType(dummy); - EXPECT_EQ(kConstNull, type); -} - -TEST_F(TypeProfilerTest, TestNormalArrayProfiling) { - int* dummy = new int[kDummyArraySize]; - const std::type_info* type; - - type = LookupType(dummy); - ASSERT_NE(kConstNull, type); - // For an array, the profiler remembers its base type. - EXPECT_STREQ(typeid(int).name(), type->name()); - delete[] dummy; - - type = LookupType(dummy); - EXPECT_EQ(kConstNull, type); -} - -TEST_F(TypeProfilerTest, TestRepeatedNewAndDelete) { - int *dummy[kDummyArraySize]; - const std::type_info* type; - for (int i = 0; i < kDummyArraySize; ++i) - dummy[i] = new int(i); - - for (int i = 0; i < kDummyArraySize; ++i) { - type = LookupType(dummy[i]); - ASSERT_NE(kConstNull, type); - EXPECT_STREQ(typeid(int).name(), type->name()); - } - - for (int i = 0; i < kDummyArraySize; ++i) { - delete dummy[i]; - type = LookupType(dummy[i]); - ASSERT_EQ(kConstNull, type); - } -} - -TEST_F(TypeProfilerTest, TestMultipleNewWithDroppingDelete) { - static const size_t large_size = 256 * 1024; - - char* dummy_char = new char[large_size / sizeof(*dummy_char)]; - const std::type_info* type; - - type = LookupType(dummy_char); - ASSERT_NE(kConstNull, type); - EXPECT_STREQ(typeid(char).name(), type->name()); - - // Call "::operator delete" directly to drop __op_delete_intercept__. - ::operator delete[](dummy_char); - - type = LookupType(dummy_char); - ASSERT_NE(kConstNull, type); - EXPECT_STREQ(typeid(char).name(), type->name()); - - // Allocates a little different size. - int* dummy_int = new int[large_size / sizeof(*dummy_int) - 1]; - - // We expect that tcmalloc returns the same address for these large (over 32k) - // allocation calls. It usually happens, but maybe probablistic. - ASSERT_EQ(static_cast<void*>(dummy_char), static_cast<void*>(dummy_int)) << - "two new (malloc) calls didn't return the same address; retry it."; - - type = LookupType(dummy_int); - ASSERT_NE(kConstNull, type); - EXPECT_STREQ(typeid(int).name(), type->name()); - - delete[] dummy_int; - - type = LookupType(dummy_int); - EXPECT_EQ(kConstNull, type); -} - -TEST_F(TypeProfilerTest, TestProfileDeleteWithoutProfiledNew) { - // 'dummy' should be new'ed in this test before intercept functions are set. - ResetInterceptFunctions(); - - int* dummy = new int(48); - const std::type_info* type; - - // Set intercept functions again after 'dummy' is new'ed. - SetInterceptFunctions(); - - delete dummy; - - type = LookupType(dummy); - EXPECT_EQ(kConstNull, type); - - ResetInterceptFunctions(); -} - -TEST_F(TypeProfilerTest, TestProfileNewWithoutProfiledDelete) { - int* dummy = new int(48); - const std::type_info* type; - - EXPECT_TRUE(Controller::IsProfiling()); - - // Stop profiling before deleting 'dummy'. - Controller::Stop(); - EXPECT_FALSE(Controller::IsProfiling()); - - delete dummy; - - // NOTE: We accept that a profile entry remains when a profiled object is - // deleted after Controller::Stop(). - type = LookupType(dummy); - ASSERT_NE(kConstNull, type); - EXPECT_STREQ(typeid(int).name(), type->name()); - - Controller::Restart(); - EXPECT_TRUE(Controller::IsProfiling()); - - // Remove manually since 'dummy' is not removed from type_profiler_map. - EraseType(dummy); -} - -} // namespace type_profiler -} // namespace base - -#endif // defined(TYPE_PROFILING) - -int main(int argc, char** argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/base/base.gypi b/base/base.gypi index ea02165..ab1f380 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -18,8 +18,6 @@ '../build/build_config.h', 'allocator/allocator_extension.cc', 'allocator/allocator_extension.h', - 'allocator/type_profiler_control.cc', - 'allocator/type_profiler_control.h', 'android/animation_frame_time_histogram.cc', 'android/animation_frame_time_histogram.h', 'android/apk_assets.cc', @@ -795,8 +793,6 @@ ], ['>(nacl_untrusted_build)==1', { 'sources!': [ - 'allocator/type_profiler_control.cc', - 'allocator/type_profiler_control.h', 'base_paths.cc', 'cpu.cc', 'debug/stack_trace.cc', diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc index 0ebf984..edae49b 100644 --- a/base/process/launch_posix.cc +++ b/base/process/launch_posix.cc @@ -22,7 +22,6 @@ #include <limits> #include <set> -#include "base/allocator/type_profiler_control.h" #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/debug/debugger.h" @@ -392,11 +391,6 @@ Process LaunchProcess(const std::vector<std::string>& argv, } } - // Stop type-profiler. - // The profiler should be stopped between fork and exec since it inserts - // locks at new/delete expressions. See http://crbug.com/36678. - base::type_profiler::Controller::Stop(); - if (options.maximize_rlimits) { // Some resource limits need to be maximal in this child. for (size_t i = 0; i < options.maximize_rlimits->size(); ++i) { @@ -593,11 +587,6 @@ static GetAppOutputInternalResult GetAppOutputInternal( if (dev_null < 0) _exit(127); - // Stop type-profiler. - // The profiler should be stopped between fork and exec since it inserts - // locks at new/delete expressions. See http://crbug.com/36678. - base::type_profiler::Controller::Stop(); - fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); fd_shuffle1.push_back(InjectionArc( include_stderr ? pipe_fd[1] : dev_null, diff --git a/build/common.gypi b/build/common.gypi index 08d1e2a..f7d2141 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -517,12 +517,6 @@ # This is intended for iOS builds only. 'use_system_libcxx%': 0, - # Use a modified version of Clang to intercept allocated types and sizes - # for allocated objects. clang_type_profiler=1 implies clang=1. - # See http://dev.chromium.org/developers/deep-memory-profiler/cpp-object-type-identifier - # TODO(dmikurube): Support mac. See http://crbug.com/123758#c11 - 'clang_type_profiler%': 0, - # Set to true to instrument the code with function call logger. # See src/third_party/cygprofile/cyg-profile.cc for details. 'order_profiling%': 0, @@ -1205,7 +1199,6 @@ 'use_prebuilt_instrumented_libraries%': '<(use_prebuilt_instrumented_libraries)', 'use_custom_libcxx%': '<(use_custom_libcxx)', 'use_system_libcxx%': '<(use_system_libcxx)', - 'clang_type_profiler%': '<(clang_type_profiler)', 'order_profiling%': '<(order_profiling)', 'order_text_section%': '<(order_text_section)', 'enable_extensions%': '<(enable_extensions)', @@ -2281,23 +2274,6 @@ 'v8_target_arch': 'arm64', }], - ['OS=="linux" and clang_type_profiler==1', { - 'clang%': 1, - 'clang_use_chrome_plugins%': 0, - 'conditions': [ - ['host_arch=="x64"', { - 'make_clang_dir%': 'third_party/llvm-allocated-type/Linux_x64', - }], - ['host_arch=="ia32"', { - # 32-bit Clang is unsupported. It may not build. Put your 32-bit - # Clang in this directory at your own risk if needed for some - # purpose (e.g. to compare 32-bit and 64-bit behavior like memory - # usage). Any failure by this compiler should not close the tree. - 'make_clang_dir%': 'third_party/llvm-allocated-type/Linux_ia32', - }], - ], - }], - # On valgrind bots, override the optimizer settings so we don't inline too # much and make the stacks harder to figure out. # @@ -2675,18 +2651,6 @@ '<(DEPTH)/build/win/asan.gyp:asan_dynamic_runtime', ], }], - ['OS=="linux" and use_allocator!="none" and clang_type_profiler==1', { - 'cflags_cc!': ['-fno-rtti'], - 'cflags_cc+': [ - '-frtti', - '-gline-tables-only', - '-fintercept-allocation-functions', - ], - 'defines': ['TYPE_PROFILING'], - 'dependencies': [ - '<(DEPTH)/base/allocator/allocator.gyp:type_profiler', - ], - }], ['branding=="Chrome"', { 'defines': ['GOOGLE_CHROME_BUILD'], }, { # else: branding!="Chrome" diff --git a/build/toolchain/android/BUILD.gn b/build/toolchain/android/BUILD.gn index ed7c407..749d28b 100644 --- a/build/toolchain/android/BUILD.gn +++ b/build/toolchain/android/BUILD.gn @@ -4,7 +4,6 @@ import("//build/config/sysroot.gni") # Imports android/config.gni. import("//build/toolchain/ccache.gni") -import("//build/toolchain/clang.gni") import("//build/toolchain/goma.gni") import("//build/toolchain/gcc_toolchain.gni") @@ -47,13 +46,8 @@ template("android_gcc_toolchain") { is_clang = invoker.is_clang if (is_clang) { - if (use_clang_type_profiler) { - prefix = rebase_path("//third_party/llvm-allocated-type/Linux_x64/bin", - root_build_dir) - } else { - prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", - root_build_dir) - } + prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", + root_build_dir) cc = "${compiler_prefix}$prefix/clang" cxx = "${compiler_prefix}$prefix/clang++" } else { diff --git a/build/toolchain/clang.gni b/build/toolchain/clang.gni deleted file mode 100644 index c680384..0000000 --- a/build/toolchain/clang.gni +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -declare_args() { - # Enable the optional type profiler in Clang, which will tag heap allocations - # with the allocation type. - use_clang_type_profiler = false -} diff --git a/build/toolchain/cros/BUILD.gn b/build/toolchain/cros/BUILD.gn index 140958b..755721b 100644 --- a/build/toolchain/cros/BUILD.gn +++ b/build/toolchain/cros/BUILD.gn @@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/toolchain/clang.gni") import("//build/toolchain/gcc_toolchain.gni") declare_args() { diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn index 9145284..94d9a16 100644 --- a/build/toolchain/linux/BUILD.gn +++ b/build/toolchain/linux/BUILD.gn @@ -4,7 +4,6 @@ import("//build/config/sysroot.gni") import("//build/toolchain/ccache.gni") -import("//build/toolchain/clang.gni") import("//build/toolchain/gcc_toolchain.gni") import("//build/toolchain/goma.gni") @@ -32,13 +31,8 @@ gcc_toolchain("arm") { } gcc_toolchain("clang_x86") { - if (use_clang_type_profiler) { - prefix = rebase_path("//third_party/llvm-allocated-type/Linux_ia32/bin", - root_build_dir) - } else { - prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", - root_build_dir) - } + prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", + root_build_dir) cc = "${compiler_prefix}$prefix/clang" cxx = "${compiler_prefix}$prefix/clang++" readelf = "readelf" @@ -66,13 +60,8 @@ gcc_toolchain("x86") { } gcc_toolchain("clang_x64") { - if (use_clang_type_profiler) { - prefix = rebase_path("//third_party/llvm-allocated-type/Linux_x64/bin", - root_build_dir) - } else { - prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", - root_build_dir) - } + prefix = rebase_path("//third_party/llvm-build/Release+Asserts/bin", + root_build_dir) cc = "${compiler_prefix}$prefix/clang" cxx = "${compiler_prefix}$prefix/clang++" diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn index 4053511..80d782f 100644 --- a/build/toolchain/mac/BUILD.gn +++ b/build/toolchain/mac/BUILD.gn @@ -11,7 +11,6 @@ import("//build/config/ios/ios_sdk.gni") assert(host_os == "mac") -import("//build/toolchain/clang.gni") import("//build/toolchain/goma.gni") if (use_goma) { diff --git a/chrome/chrome_exe.gypi b/chrome/chrome_exe.gypi index f6976c2..c64b27d 100644 --- a/chrome/chrome_exe.gypi +++ b/chrome/chrome_exe.gypi @@ -9,11 +9,6 @@ 'type': 'none', 'dependencies': [ 'chrome_initial', ], 'conditions': [ - ['OS=="linux" and clang_type_profiler==1', { - 'dependencies!': [ - '<(DEPTH)/base/allocator/allocator.gyp:type_profiler', - ], - }], ['OS == "win"', { 'actions': [ { diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc index f35ed29..7e6d6db 100644 --- a/content/app/content_main_runner.cc +++ b/content/app/content_main_runner.cc @@ -60,10 +60,6 @@ #if defined(USE_TCMALLOC) #include "third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h" -#if defined(TYPE_PROFILING) -#include "base/allocator/type_profiler.h" -#include "base/allocator/type_profiler_tcmalloc.h" -#endif #endif #if !defined(OS_IOS) @@ -464,13 +460,6 @@ class ContentMainRunnerImpl : public ContentMainRunner { // implement this EnableTerminationOnOutOfMemory() function. Whateverz. // This works for now. #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) - -#if defined(TYPE_PROFILING) - base::type_profiler::InterceptFunctions::SetFunctions( - base::type_profiler::NewInterceptForTCMalloc, - base::type_profiler::DeleteInterceptForTCMalloc); -#endif - // For tcmalloc, we need to tell it to behave like new. tc_set_new_mode(1); diff --git a/third_party/tcmalloc/chromium/src/deep-heap-profile.cc b/third_party/tcmalloc/chromium/src/deep-heap-profile.cc deleted file mode 100644 index bbf002a..0000000 --- a/third_party/tcmalloc/chromium/src/deep-heap-profile.cc +++ /dev/null @@ -1,1161 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// --- -// Author: Sainbayar Sukhbaatar -// Dai Mikurube -// - -#include "deep-heap-profile.h" - -#ifdef USE_DEEP_HEAP_PROFILE -#include <algorithm> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <time.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> // for getpagesize and getpid -#endif // HAVE_UNISTD_H - -#if defined(__linux__) -#include <endian.h> -#if !defined(__LITTLE_ENDIAN__) and !defined(__BIG_ENDIAN__) -#if __BYTE_ORDER == __BIG_ENDIAN -#define __BIG_ENDIAN__ -#endif // __BYTE_ORDER == __BIG_ENDIAN -#endif // !defined(__LITTLE_ENDIAN__) and !defined(__BIG_ENDIAN__) -#if defined(__BIG_ENDIAN__) -#include <byteswap.h> -#endif // defined(__BIG_ENDIAN__) -#endif // defined(__linux__) -#if defined(COMPILER_MSVC) -#include <Winsock2.h> // for gethostname -#endif // defined(COMPILER_MSVC) - -#include "base/cycleclock.h" -#include "base/sysinfo.h" -#include "internal_logging.h" // for ASSERT, etc - -static const int kProfilerBufferSize = 1 << 20; -static const int kHashTableSize = 179999; // Same as heap-profile-table.cc. - -static const int PAGEMAP_BYTES = 8; -static const int KPAGECOUNT_BYTES = 8; -static const uint64 MAX_ADDRESS = kuint64max; - -// Tag strings in heap profile dumps. -static const char kProfileHeader[] = "heap profile: "; -static const char kProfileVersion[] = "DUMP_DEEP_6"; -static const char kMetaInformationHeader[] = "META:\n"; -static const char kMMapListHeader[] = "MMAP_LIST:\n"; -static const char kGlobalStatsHeader[] = "GLOBAL_STATS:\n"; -static const char kStacktraceHeader[] = "STACKTRACES:\n"; -static const char kProcSelfMapsHeader[] = "\nMAPPED_LIBRARIES:\n"; - -static const char kVirtualLabel[] = "virtual"; -static const char kCommittedLabel[] = "committed"; - -#if defined(__linux__) -#define OS_NAME "linux" -#elif defined(_WIN32) || defined(_WIN64) -#define OS_NAME "windows" -#else -#define OS_NAME "unknown-os" -#endif - -bool DeepHeapProfile::AppendCommandLine(TextBuffer* buffer) { -#if defined(__linux__) - RawFD fd; - char filename[100]; - char cmdline[4096]; - snprintf(filename, sizeof(filename), "/proc/%d/cmdline", - static_cast<int>(getpid())); - fd = open(filename, O_RDONLY); - if (fd == kIllegalRawFD) { - RAW_VLOG(0, "Failed to open /proc/self/cmdline"); - return false; - } - - size_t length = read(fd, cmdline, sizeof(cmdline) - 1); - close(fd); - - for (int i = 0; i < length; ++i) - if (cmdline[i] == '\0') - cmdline[i] = ' '; - cmdline[length] = '\0'; - - buffer->AppendString("CommandLine: ", 0); - buffer->AppendString(cmdline, 0); - buffer->AppendChar('\n'); - - return true; -#else - return false; -#endif -} - -#if defined(_WIN32) || defined(_WIN64) - -// TODO(peria): Implement this function. -void DeepHeapProfile::MemoryInfoGetterWindows::Initialize() { -} - -// TODO(peria): Implement this function. -size_t DeepHeapProfile::MemoryInfoGetterWindows::CommittedSize( - uint64 first_address, - uint64 last_address, - TextBuffer* buffer) const { - return 0; -} - -// TODO(peria): Implement this function. -bool DeepHeapProfile::MemoryInfoGetterWindows::IsPageCountAvailable() const { - return false; -} - -#endif // defined(_WIN32) || defined(_WIN64) - -#if defined(__linux__) - -void DeepHeapProfile::MemoryInfoGetterLinux::Initialize() { - char filename[100]; - snprintf(filename, sizeof(filename), "/proc/%d/pagemap", - static_cast<int>(getpid())); - pagemap_fd_ = open(filename, O_RDONLY); - RAW_CHECK(pagemap_fd_ != -1, "Failed to open /proc/self/pagemap"); - - if (pageframe_type_ == DUMP_PAGECOUNT) { - snprintf(filename, sizeof(filename), "/proc/kpagecount"); - kpagecount_fd_ = open(filename, O_RDONLY); - if (kpagecount_fd_ == -1) - RAW_VLOG(0, "Failed to open /proc/kpagecount"); - } -} - -size_t DeepHeapProfile::MemoryInfoGetterLinux::CommittedSize( - uint64 first_address, - uint64 last_address, - DeepHeapProfile::TextBuffer* buffer) const { - int page_size = getpagesize(); - uint64 page_address = (first_address / page_size) * page_size; - size_t committed_size = 0; - size_t pageframe_list_length = 0; - - Seek(first_address); - - // Check every page on which the allocation resides. - while (page_address <= last_address) { - // Read corresponding physical page. - State state; - // TODO(dmikurube): Read pagemap in bulk for speed. - // TODO(dmikurube): Consider using mincore(2). - if (Read(&state, pageframe_type_ != DUMP_NO_PAGEFRAME) == false) { - // We can't read the last region (e.g vsyscall). -#ifndef NDEBUG - RAW_VLOG(0, "pagemap read failed @ %#llx %" PRId64 " bytes", - first_address, last_address - first_address + 1); -#endif - return 0; - } - - // Dump pageframes of resident pages. Non-resident pages are just skipped. - if (pageframe_type_ != DUMP_NO_PAGEFRAME && - buffer != NULL && state.pfn != 0) { - if (pageframe_list_length == 0) { - buffer->AppendString(" PF:", 0); - pageframe_list_length = 5; - } - buffer->AppendChar(' '); - if (page_address < first_address) - buffer->AppendChar('<'); - buffer->AppendBase64(state.pfn, 4); - pageframe_list_length += 5; - if (pageframe_type_ == DUMP_PAGECOUNT && IsPageCountAvailable()) { - uint64 pagecount = ReadPageCount(state.pfn); - // Assume pagecount == 63 if the pageframe is mapped more than 63 times. - if (pagecount > 63) - pagecount = 63; - buffer->AppendChar('#'); - buffer->AppendBase64(pagecount, 1); - pageframe_list_length += 2; - } - if (last_address < page_address - 1 + page_size) - buffer->AppendChar('>'); - // Begins a new line every 94 characters. - if (pageframe_list_length > 94) { - buffer->AppendChar('\n'); - pageframe_list_length = 0; - } - } - - if (state.is_committed) { - // Calculate the size of the allocation part in this page. - size_t bytes = page_size; - - // If looking at the last page in a given region. - if (last_address <= page_address - 1 + page_size) { - bytes = last_address - page_address + 1; - } - - // If looking at the first page in a given region. - if (page_address < first_address) { - bytes -= first_address - page_address; - } - - committed_size += bytes; - } - if (page_address > MAX_ADDRESS - page_size) { - break; - } - page_address += page_size; - } - - if (pageframe_type_ != DUMP_NO_PAGEFRAME && - buffer != NULL && pageframe_list_length != 0) { - buffer->AppendChar('\n'); - } - - return committed_size; -} - -uint64 DeepHeapProfile::MemoryInfoGetterLinux::ReadPageCount(uint64 pfn) const { - int64 index = pfn * KPAGECOUNT_BYTES; - int64 offset = lseek64(kpagecount_fd_, index, SEEK_SET); - RAW_DCHECK(offset == index, "Failed in seeking in kpagecount."); - - uint64 kpagecount_value; - int result = read(kpagecount_fd_, &kpagecount_value, KPAGECOUNT_BYTES); - if (result != KPAGECOUNT_BYTES) - return 0; - - return kpagecount_value; -} - -bool DeepHeapProfile::MemoryInfoGetterLinux::Seek(uint64 address) const { - int64 index = (address / getpagesize()) * PAGEMAP_BYTES; - RAW_DCHECK(pagemap_fd_ != -1, "Failed to seek in /proc/self/pagemap"); - int64 offset = lseek64(pagemap_fd_, index, SEEK_SET); - RAW_DCHECK(offset == index, "Failed in seeking."); - return offset >= 0; -} - -bool DeepHeapProfile::MemoryInfoGetterLinux::Read( - State* state, bool get_pfn) const { - static const uint64 U64_1 = 1; - static const uint64 PFN_FILTER = (U64_1 << 55) - U64_1; - static const uint64 PAGE_PRESENT = U64_1 << 63; - static const uint64 PAGE_SWAP = U64_1 << 62; - static const uint64 PAGE_RESERVED = U64_1 << 61; - static const uint64 FLAG_NOPAGE = U64_1 << 20; - static const uint64 FLAG_KSM = U64_1 << 21; - static const uint64 FLAG_MMAP = U64_1 << 11; - - uint64 pagemap_value; - RAW_DCHECK(pagemap_fd_ != -1, "Failed to read from /proc/self/pagemap"); - int result = read(pagemap_fd_, &pagemap_value, PAGEMAP_BYTES); - if (result != PAGEMAP_BYTES) { - return false; - } - - // Check if the page is committed. - state->is_committed = (pagemap_value & (PAGE_PRESENT | PAGE_SWAP)); - - state->is_present = (pagemap_value & PAGE_PRESENT); - state->is_swapped = (pagemap_value & PAGE_SWAP); - state->is_shared = false; - - if (get_pfn && state->is_present && !state->is_swapped) - state->pfn = (pagemap_value & PFN_FILTER); - else - state->pfn = 0; - - return true; -} - -bool DeepHeapProfile::MemoryInfoGetterLinux::IsPageCountAvailable() const { - return kpagecount_fd_ != -1; -} - -#endif // defined(__linux__) - -DeepHeapProfile::MemoryResidenceInfoGetterInterface:: - MemoryResidenceInfoGetterInterface() {} - -DeepHeapProfile::MemoryResidenceInfoGetterInterface:: - ~MemoryResidenceInfoGetterInterface() {} - -DeepHeapProfile::MemoryResidenceInfoGetterInterface* - DeepHeapProfile::MemoryResidenceInfoGetterInterface::Create( - PageFrameType pageframe_type) { -#if defined(_WIN32) || defined(_WIN64) - return new MemoryInfoGetterWindows(pageframe_type); -#elif defined(__linux__) - return new MemoryInfoGetterLinux(pageframe_type); -#else - return NULL; -#endif -} - -DeepHeapProfile::DeepHeapProfile(HeapProfileTable* heap_profile, - const char* prefix, - enum PageFrameType pageframe_type) - : memory_residence_info_getter_( - MemoryResidenceInfoGetterInterface::Create(pageframe_type)), - most_recent_pid_(-1), - stats_(), - dump_count_(0), - filename_prefix_(NULL), - deep_table_(kHashTableSize, heap_profile->alloc_, heap_profile->dealloc_), - pageframe_type_(pageframe_type), - heap_profile_(heap_profile) { - // Copy filename prefix. - const int prefix_length = strlen(prefix); - filename_prefix_ = - reinterpret_cast<char*>(heap_profile_->alloc_(prefix_length + 1)); - memcpy(filename_prefix_, prefix, prefix_length); - filename_prefix_[prefix_length] = '\0'; - - strncpy(run_id_, "undetermined-run-id", sizeof(run_id_)); -} - -DeepHeapProfile::~DeepHeapProfile() { - heap_profile_->dealloc_(filename_prefix_); - delete memory_residence_info_getter_; -} - -// Global malloc() should not be used in this function. -// Use LowLevelAlloc if required. -void DeepHeapProfile::DumpOrderedProfile(const char* reason, - char raw_buffer[], - int buffer_size, - RawFD fd) { - TextBuffer buffer(raw_buffer, buffer_size, fd); - -#ifndef NDEBUG - int64 starting_cycles = CycleClock::Now(); -#endif - - // Get the time before starting snapshot. - // TODO(dmikurube): Consider gettimeofday if available. - time_t time_value = time(NULL); - - ++dump_count_; - - // Re-open files in /proc/pid/ if the process is newly forked one. - if (most_recent_pid_ != getpid()) { - char hostname[64]; - if (0 == gethostname(hostname, sizeof(hostname))) { - char* dot = strchr(hostname, '.'); - if (dot != NULL) - *dot = '\0'; - } else { - strcpy(hostname, "unknown"); - } - - most_recent_pid_ = getpid(); - - snprintf(run_id_, sizeof(run_id_), "%s-" OS_NAME "-%d-%lu", - hostname, most_recent_pid_, time(NULL)); - - if (memory_residence_info_getter_) - memory_residence_info_getter_->Initialize(); - deep_table_.ResetIsLogged(); - - // Write maps into "|filename_prefix_|.<pid>.maps". - WriteProcMaps(filename_prefix_, raw_buffer, buffer_size); - } - - // Reset committed sizes of buckets. - deep_table_.ResetCommittedSize(); - - // Record committed sizes. - stats_.SnapshotAllocations(this); - - // TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf. - // glibc's snprintf internally allocates memory by alloca normally, but it - // allocates memory by malloc if large memory is required. - - buffer.AppendString(kProfileHeader, 0); - buffer.AppendString(kProfileVersion, 0); - buffer.AppendString("\n", 0); - - // Fill buffer with meta information. - buffer.AppendString(kMetaInformationHeader, 0); - - buffer.AppendString("Time: ", 0); - buffer.AppendUnsignedLong(time_value, 0); - buffer.AppendChar('\n'); - - if (reason != NULL) { - buffer.AppendString("Reason: ", 0); - buffer.AppendString(reason, 0); - buffer.AppendChar('\n'); - } - - AppendCommandLine(&buffer); - - buffer.AppendString("RunID: ", 0); - buffer.AppendString(run_id_, 0); - buffer.AppendChar('\n'); - - buffer.AppendString("PageSize: ", 0); - buffer.AppendInt(getpagesize(), 0, 0); - buffer.AppendChar('\n'); - - // Assumes the physical memory <= 64GB (PFN < 2^24). - if (pageframe_type_ == DUMP_PAGECOUNT && memory_residence_info_getter_ && - memory_residence_info_getter_->IsPageCountAvailable()) { - buffer.AppendString("PageFrame: 24,Base64,PageCount", 0); - buffer.AppendChar('\n'); - } else if (pageframe_type_ != DUMP_NO_PAGEFRAME) { - buffer.AppendString("PageFrame: 24,Base64", 0); - buffer.AppendChar('\n'); - } - - // Fill buffer with the global stats. - buffer.AppendString(kMMapListHeader, 0); - - stats_.SnapshotMaps(memory_residence_info_getter_, this, &buffer); - - // Fill buffer with the global stats. - buffer.AppendString(kGlobalStatsHeader, 0); - - stats_.Unparse(&buffer); - - buffer.AppendString(kStacktraceHeader, 0); - buffer.AppendString(kVirtualLabel, 10); - buffer.AppendChar(' '); - buffer.AppendString(kCommittedLabel, 10); - buffer.AppendString("\n", 0); - - // Fill buffer. - deep_table_.UnparseForStats(&buffer); - - buffer.Flush(); - - // Write the bucket listing into a .bucket file. - deep_table_.WriteForBucketFile( - filename_prefix_, dump_count_, raw_buffer, buffer_size); - -#ifndef NDEBUG - int64 elapsed_cycles = CycleClock::Now() - starting_cycles; - double elapsed_seconds = elapsed_cycles / CyclesPerSecond(); - RAW_VLOG(0, "Time spent on DeepProfiler: %.3f sec\n", elapsed_seconds); -#endif -} - -int DeepHeapProfile::TextBuffer::Size() { - return size_; -} - -int DeepHeapProfile::TextBuffer::FilledBytes() { - return cursor_; -} - -void DeepHeapProfile::TextBuffer::Clear() { - cursor_ = 0; -} - -void DeepHeapProfile::TextBuffer::Flush() { - RawWrite(fd_, buffer_, cursor_); - cursor_ = 0; -} - -// TODO(dmikurube): These Append* functions should not use snprintf. -bool DeepHeapProfile::TextBuffer::AppendChar(char value) { - return ForwardCursor(snprintf(buffer_ + cursor_, size_ - cursor_, - "%c", value)); -} - -bool DeepHeapProfile::TextBuffer::AppendString(const char* value, int width) { - char* position = buffer_ + cursor_; - int available = size_ - cursor_; - int appended; - if (width == 0) - appended = snprintf(position, available, "%s", value); - else - appended = snprintf(position, available, "%*s", - width, value); - return ForwardCursor(appended); -} - -bool DeepHeapProfile::TextBuffer::AppendInt(int value, int width, - bool leading_zero) { - char* position = buffer_ + cursor_; - int available = size_ - cursor_; - int appended; - if (width == 0) - appended = snprintf(position, available, "%d", value); - else if (leading_zero) - appended = snprintf(position, available, "%0*d", width, value); - else - appended = snprintf(position, available, "%*d", width, value); - return ForwardCursor(appended); -} - -bool DeepHeapProfile::TextBuffer::AppendLong(long value, int width) { - char* position = buffer_ + cursor_; - int available = size_ - cursor_; - int appended; - if (width == 0) - appended = snprintf(position, available, "%ld", value); - else - appended = snprintf(position, available, "%*ld", width, value); - return ForwardCursor(appended); -} - -bool DeepHeapProfile::TextBuffer::AppendUnsignedLong(unsigned long value, - int width) { - char* position = buffer_ + cursor_; - int available = size_ - cursor_; - int appended; - if (width == 0) - appended = snprintf(position, available, "%lu", value); - else - appended = snprintf(position, available, "%*lu", width, value); - return ForwardCursor(appended); -} - -bool DeepHeapProfile::TextBuffer::AppendInt64(int64 value, int width) { - char* position = buffer_ + cursor_; - int available = size_ - cursor_; - int appended; - if (width == 0) - appended = snprintf(position, available, "%" PRId64, value); - else - appended = snprintf(position, available, "%*" PRId64, width, value); - return ForwardCursor(appended); -} - -bool DeepHeapProfile::TextBuffer::AppendPtr(uint64 value, int width) { - char* position = buffer_ + cursor_; - int available = size_ - cursor_; - int appended; - if (width == 0) - appended = snprintf(position, available, "%" PRIx64, value); - else - appended = snprintf(position, available, "%0*" PRIx64, width, value); - return ForwardCursor(appended); -} - -bool DeepHeapProfile::TextBuffer::AppendBase64(uint64 value, int width) { - static const char base64[65] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -#if defined(__BIG_ENDIAN__) - value = bswap_64(value); -#endif - for (int shift = (width - 1) * 6; shift >= 0; shift -= 6) { - if (!AppendChar(base64[(value >> shift) & 0x3f])) - return false; - } - return true; -} - -bool DeepHeapProfile::TextBuffer::ForwardCursor(int appended) { - if (appended < 0 || appended >= size_ - cursor_) - return false; - cursor_ += appended; - if (cursor_ > size_ * 4 / 5) - Flush(); - return true; -} - -void DeepHeapProfile::DeepBucket::UnparseForStats(TextBuffer* buffer) { - buffer->AppendInt64(bucket->alloc_size - bucket->free_size, 10); - buffer->AppendChar(' '); - buffer->AppendInt64(committed_size, 10); - buffer->AppendChar(' '); - buffer->AppendInt(bucket->allocs, 6, false); - buffer->AppendChar(' '); - buffer->AppendInt(bucket->frees, 6, false); - buffer->AppendString(" @ ", 0); - buffer->AppendInt(id, 0, false); - buffer->AppendString("\n", 0); -} - -void DeepHeapProfile::DeepBucket::UnparseForBucketFile(TextBuffer* buffer) { - buffer->AppendInt(id, 0, false); - buffer->AppendChar(' '); - buffer->AppendString(is_mmap ? "mmap" : "malloc", 0); - -#if defined(TYPE_PROFILING) - buffer->AppendString(" t0x", 0); - buffer->AppendPtr(reinterpret_cast<uintptr_t>(type), 0); - if (type == NULL) { - buffer->AppendString(" nno_typeinfo", 0); - } else { - buffer->AppendString(" n", 0); - buffer->AppendString(type->name(), 0); - } -#endif - - for (int depth = 0; depth < bucket->depth; depth++) { - buffer->AppendString(" 0x", 0); - buffer->AppendPtr(reinterpret_cast<uintptr_t>(bucket->stack[depth]), 8); - } - buffer->AppendString("\n", 0); -} - -DeepHeapProfile::DeepBucketTable::DeepBucketTable( - int table_size, - HeapProfileTable::Allocator alloc, - HeapProfileTable::DeAllocator dealloc) - : table_(NULL), - table_size_(table_size), - alloc_(alloc), - dealloc_(dealloc), - bucket_id_(0) { - const int bytes = table_size * sizeof(DeepBucket*); - table_ = reinterpret_cast<DeepBucket**>(alloc(bytes)); - memset(table_, 0, bytes); -} - -DeepHeapProfile::DeepBucketTable::~DeepBucketTable() { - ASSERT(table_ != NULL); - for (int db = 0; db < table_size_; db++) { - for (DeepBucket* x = table_[db]; x != 0; /**/) { - DeepBucket* db = x; - x = x->next; - dealloc_(db); - } - } - dealloc_(table_); -} - -DeepHeapProfile::DeepBucket* DeepHeapProfile::DeepBucketTable::Lookup( - Bucket* bucket, -#if defined(TYPE_PROFILING) - const std::type_info* type, -#endif - bool is_mmap) { - // Make hash-value - uintptr_t h = 0; - - AddToHashValue(reinterpret_cast<uintptr_t>(bucket), &h); - if (is_mmap) { - AddToHashValue(1, &h); - } else { - AddToHashValue(0, &h); - } - -#if defined(TYPE_PROFILING) - if (type == NULL) { - AddToHashValue(0, &h); - } else { - AddToHashValue(reinterpret_cast<uintptr_t>(type->name()), &h); - } -#endif - - FinishHashValue(&h); - - // Lookup stack trace in table - unsigned int buck = ((unsigned int) h) % table_size_; - for (DeepBucket* db = table_[buck]; db != 0; db = db->next) { - if (db->bucket == bucket) { - return db; - } - } - - // Create a new bucket - DeepBucket* db = reinterpret_cast<DeepBucket*>(alloc_(sizeof(DeepBucket))); - memset(db, 0, sizeof(*db)); - db->bucket = bucket; -#if defined(TYPE_PROFILING) - db->type = type; -#endif - db->committed_size = 0; - db->is_mmap = is_mmap; - db->id = (bucket_id_++); - db->is_logged = false; - db->next = table_[buck]; - table_[buck] = db; - return db; -} - -// TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf. -void DeepHeapProfile::DeepBucketTable::UnparseForStats(TextBuffer* buffer) { - for (int i = 0; i < table_size_; i++) { - for (DeepBucket* deep_bucket = table_[i]; - deep_bucket != NULL; - deep_bucket = deep_bucket->next) { - Bucket* bucket = deep_bucket->bucket; - if (bucket->alloc_size - bucket->free_size == 0) { - continue; // Skip empty buckets. - } - deep_bucket->UnparseForStats(buffer); - } - } -} - -void DeepHeapProfile::DeepBucketTable::WriteForBucketFile( - const char* prefix, int dump_count, char raw_buffer[], int buffer_size) { - char filename[100]; - snprintf(filename, sizeof(filename), - "%s.%05d.%04d.buckets", prefix, getpid(), dump_count); - RawFD fd = RawOpenForWriting(filename); - RAW_DCHECK(fd != kIllegalRawFD, ""); - - TextBuffer buffer(raw_buffer, buffer_size, fd); - - for (int i = 0; i < table_size_; i++) { - for (DeepBucket* deep_bucket = table_[i]; - deep_bucket != NULL; - deep_bucket = deep_bucket->next) { - Bucket* bucket = deep_bucket->bucket; - if (deep_bucket->is_logged) { - continue; // Skip the bucket if it is already logged. - } - if (!deep_bucket->is_mmap && - bucket->alloc_size - bucket->free_size <= 64) { - continue; // Skip small malloc buckets. - } - - deep_bucket->UnparseForBucketFile(&buffer); - deep_bucket->is_logged = true; - } - } - - buffer.Flush(); - RawClose(fd); -} - -void DeepHeapProfile::DeepBucketTable::ResetCommittedSize() { - for (int i = 0; i < table_size_; i++) { - for (DeepBucket* deep_bucket = table_[i]; - deep_bucket != NULL; - deep_bucket = deep_bucket->next) { - deep_bucket->committed_size = 0; - } - } -} - -void DeepHeapProfile::DeepBucketTable::ResetIsLogged() { - for (int i = 0; i < table_size_; i++) { - for (DeepBucket* deep_bucket = table_[i]; - deep_bucket != NULL; - deep_bucket = deep_bucket->next) { - deep_bucket->is_logged = false; - } - } -} - -// This hash function is from HeapProfileTable::GetBucket. -// static -void DeepHeapProfile::DeepBucketTable::AddToHashValue( - uintptr_t add, uintptr_t* hash_value) { - *hash_value += add; - *hash_value += *hash_value << 10; - *hash_value ^= *hash_value >> 6; -} - -// This hash function is from HeapProfileTable::GetBucket. -// static -void DeepHeapProfile::DeepBucketTable::FinishHashValue(uintptr_t* hash_value) { - *hash_value += *hash_value << 3; - *hash_value ^= *hash_value >> 11; -} - -void DeepHeapProfile::RegionStats::Initialize() { - virtual_bytes_ = 0; - committed_bytes_ = 0; -} - -uint64 DeepHeapProfile::RegionStats::Record( - const MemoryResidenceInfoGetterInterface* memory_residence_info_getter, - uint64 first_address, - uint64 last_address, - TextBuffer* buffer) { - uint64 committed = 0; - virtual_bytes_ += static_cast<size_t>(last_address - first_address + 1); - if (memory_residence_info_getter) - committed = memory_residence_info_getter->CommittedSize(first_address, - last_address, - buffer); - committed_bytes_ += committed; - return committed; -} - -void DeepHeapProfile::RegionStats::Unparse(const char* name, - TextBuffer* buffer) { - buffer->AppendString(name, 25); - buffer->AppendChar(' '); - buffer->AppendLong(virtual_bytes_, 12); - buffer->AppendChar(' '); - buffer->AppendLong(committed_bytes_, 12); - buffer->AppendString("\n", 0); -} - -// Snapshots all virtual memory mapping stats by merging mmap(2) records from -// MemoryRegionMap and /proc/maps, the OS-level memory mapping information. -// Memory regions described in /proc/maps, but which are not created by mmap, -// are accounted as "unhooked" memory regions. -// -// This function assumes that every memory region created by mmap is covered -// by VMA(s) described in /proc/maps except for http://crbug.com/189114. -// Note that memory regions created with mmap don't align with borders of VMAs -// in /proc/maps. In other words, a memory region by mmap can cut across many -// VMAs. Also, of course a VMA can include many memory regions by mmap. -// It means that the following situation happens: -// -// => Virtual address -// <----- VMA #1 -----><----- VMA #2 ----->...<----- VMA #3 -----><- VMA #4 -> -// ..< mmap #1 >.<- mmap #2 -><- mmap #3 ->...<- mmap #4 ->..<-- mmap #5 -->.. -// -// It can happen easily as permission can be changed by mprotect(2) for a part -// of a memory region. A change in permission splits VMA(s). -// -// To deal with the situation, this function iterates over MemoryRegionMap and -// /proc/maps independently. The iterator for MemoryRegionMap is initialized -// at the top outside the loop for /proc/maps, and it goes forward inside the -// loop while comparing their addresses. -// -// TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf. -void DeepHeapProfile::GlobalStats::SnapshotMaps( - const MemoryResidenceInfoGetterInterface* memory_residence_info_getter, - DeepHeapProfile* deep_profile, - TextBuffer* mmap_dump_buffer) { - MemoryRegionMap::LockHolder lock_holder; - ProcMapsIterator::Buffer procmaps_iter_buffer; - ProcMapsIterator procmaps_iter(0, &procmaps_iter_buffer); - uint64 vma_start_addr, vma_last_addr, offset; - int64 inode; - char* flags; - char* filename; - enum MapsRegionType type; - - for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) { - all_[i].Initialize(); - unhooked_[i].Initialize(); - } - profiled_mmap_.Initialize(); - - MemoryRegionMap::RegionIterator mmap_iter = - MemoryRegionMap::BeginRegionLocked(); - DeepBucket* deep_bucket = NULL; - if (mmap_iter != MemoryRegionMap::EndRegionLocked()) { - deep_bucket = GetInformationOfMemoryRegion( - mmap_iter, memory_residence_info_getter, deep_profile); - } - - while (procmaps_iter.Next(&vma_start_addr, &vma_last_addr, - &flags, &offset, &inode, &filename)) { - if (mmap_dump_buffer) { - char buffer[1024]; - int written = procmaps_iter.FormatLine(buffer, sizeof(buffer), - vma_start_addr, vma_last_addr, - flags, offset, inode, filename, 0); - mmap_dump_buffer->AppendString(buffer, 0); - } - - // 'vma_last_addr' should be the last inclusive address of the region. - vma_last_addr -= 1; - if (strcmp("[vsyscall]", filename) == 0) { - continue; // Reading pagemap will fail in [vsyscall]. - } - - // TODO(dmikurube): |type| will be deprecated in the dump. - // See http://crbug.com/245603. - type = ABSENT; - if (filename[0] == '/') { - if (flags[2] == 'x') - type = FILE_EXEC; - else - type = FILE_NONEXEC; - } else if (filename[0] == '\0' || filename[0] == '\n') { - type = ANONYMOUS; - } else if (strcmp(filename, "[stack]") == 0) { - type = STACK; - } else { - type = OTHER; - } - // TODO(dmikurube): This |all_| count should be removed in future soon. - // See http://crbug.com/245603. - uint64 vma_total = all_[type].Record( - memory_residence_info_getter, vma_start_addr, vma_last_addr, NULL); - uint64 vma_subtotal = 0; - - // TODO(dmikurube): Stop double-counting pagemap. - // It will be fixed when http://crbug.com/245603 finishes. - if (MemoryRegionMap::IsRecordingLocked()) { - uint64 cursor = vma_start_addr; - bool first = true; - - // Iterates over MemoryRegionMap until the iterator moves out of the VMA. - do { - if (!first) { - cursor = mmap_iter->end_addr; - ++mmap_iter; - // Don't break here even if mmap_iter == EndRegionLocked(). - - if (mmap_iter != MemoryRegionMap::EndRegionLocked()) { - deep_bucket = GetInformationOfMemoryRegion( - mmap_iter, memory_residence_info_getter, deep_profile); - } - } - first = false; - - uint64 last_address_of_unhooked; - // If the next mmap entry is away from the current VMA. - if (mmap_iter == MemoryRegionMap::EndRegionLocked() || - mmap_iter->start_addr > vma_last_addr) { - last_address_of_unhooked = vma_last_addr; - } else { - last_address_of_unhooked = mmap_iter->start_addr - 1; - } - - if (last_address_of_unhooked + 1 > cursor) { - RAW_CHECK(cursor >= vma_start_addr, - "Wrong calculation for unhooked"); - RAW_CHECK(last_address_of_unhooked <= vma_last_addr, - "Wrong calculation for unhooked"); - uint64 committed_size = unhooked_[type].Record( - memory_residence_info_getter, - cursor, - last_address_of_unhooked, - mmap_dump_buffer); - vma_subtotal += committed_size; - if (mmap_dump_buffer) { - mmap_dump_buffer->AppendString(" ", 0); - mmap_dump_buffer->AppendPtr(cursor, 0); - mmap_dump_buffer->AppendString(" - ", 0); - mmap_dump_buffer->AppendPtr(last_address_of_unhooked + 1, 0); - mmap_dump_buffer->AppendString(" unhooked ", 0); - mmap_dump_buffer->AppendInt64(committed_size, 0); - mmap_dump_buffer->AppendString(" / ", 0); - mmap_dump_buffer->AppendInt64( - last_address_of_unhooked - cursor + 1, 0); - mmap_dump_buffer->AppendString("\n", 0); - } - cursor = last_address_of_unhooked + 1; - } - - if (mmap_iter != MemoryRegionMap::EndRegionLocked() && - mmap_iter->start_addr <= vma_last_addr && - mmap_dump_buffer) { - bool trailing = mmap_iter->start_addr < vma_start_addr; - bool continued = mmap_iter->end_addr - 1 > vma_last_addr; - uint64 partial_first_address, partial_last_address; - if (trailing) - partial_first_address = vma_start_addr; - else - partial_first_address = mmap_iter->start_addr; - if (continued) - partial_last_address = vma_last_addr; - else - partial_last_address = mmap_iter->end_addr - 1; - uint64 committed_size = 0; - if (memory_residence_info_getter) - committed_size = memory_residence_info_getter->CommittedSize( - partial_first_address, partial_last_address, mmap_dump_buffer); - vma_subtotal += committed_size; - mmap_dump_buffer->AppendString(trailing ? " (" : " ", 0); - mmap_dump_buffer->AppendPtr(mmap_iter->start_addr, 0); - mmap_dump_buffer->AppendString(trailing ? ")" : " ", 0); - mmap_dump_buffer->AppendString("-", 0); - mmap_dump_buffer->AppendString(continued ? "(" : " ", 0); - mmap_dump_buffer->AppendPtr(mmap_iter->end_addr, 0); - mmap_dump_buffer->AppendString(continued ? ")" : " ", 0); - mmap_dump_buffer->AppendString(" hooked ", 0); - mmap_dump_buffer->AppendInt64(committed_size, 0); - mmap_dump_buffer->AppendString(" / ", 0); - mmap_dump_buffer->AppendInt64( - partial_last_address - partial_first_address + 1, 0); - mmap_dump_buffer->AppendString(" @ ", 0); - if (deep_bucket != NULL) { - mmap_dump_buffer->AppendInt(deep_bucket->id, 0, false); - } else { - mmap_dump_buffer->AppendInt(0, 0, false); - } - mmap_dump_buffer->AppendString("\n", 0); - } - } while (mmap_iter != MemoryRegionMap::EndRegionLocked() && - mmap_iter->end_addr - 1 <= vma_last_addr); - } - - if (vma_total != vma_subtotal) { - char buffer[1024]; - int written = procmaps_iter.FormatLine(buffer, sizeof(buffer), - vma_start_addr, vma_last_addr, - flags, offset, inode, filename, 0); - RAW_VLOG(0, "[%d] Mismatched total in VMA %" PRId64 ":" - "%" PRId64 " (%" PRId64 ")", - getpid(), vma_total, vma_subtotal, vma_total - vma_subtotal); - RAW_VLOG(0, "[%d] in %s", getpid(), buffer); - } - } - - // TODO(dmikurube): Investigate and fix http://crbug.com/189114. - // - // The total committed memory usage in all_ (from /proc/<pid>/maps) is - // sometimes smaller than the sum of the committed mmap'ed addresses and - // unhooked regions. Within our observation, the difference was only 4KB - // in committed usage, zero in reserved virtual addresses - // - // A guess is that an uncommitted (but reserved) page may become committed - // during counting memory usage in the loop above. - // - // The difference is accounted as "ABSENT" to investigate such cases. - // - // It will be fixed when http://crbug.com/245603 finishes (no double count). - - RegionStats all_total; - RegionStats unhooked_total; - for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) { - all_total.AddAnotherRegionStat(all_[i]); - unhooked_total.AddAnotherRegionStat(unhooked_[i]); - } - - size_t absent_virtual = profiled_mmap_.virtual_bytes() + - unhooked_total.virtual_bytes() - - all_total.virtual_bytes(); - if (absent_virtual > 0) - all_[ABSENT].AddToVirtualBytes(absent_virtual); - - size_t absent_committed = profiled_mmap_.committed_bytes() + - unhooked_total.committed_bytes() - - all_total.committed_bytes(); - if (absent_committed > 0) - all_[ABSENT].AddToCommittedBytes(absent_committed); -} - -void DeepHeapProfile::GlobalStats::SnapshotAllocations( - DeepHeapProfile* deep_profile) { - profiled_malloc_.Initialize(); - - deep_profile->heap_profile_->address_map_->Iterate(RecordAlloc, deep_profile); -} - -void DeepHeapProfile::GlobalStats::Unparse(TextBuffer* buffer) { - RegionStats all_total; - RegionStats unhooked_total; - for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) { - all_total.AddAnotherRegionStat(all_[i]); - unhooked_total.AddAnotherRegionStat(unhooked_[i]); - } - - // "# total (%lu) %c= profiled-mmap (%lu) + nonprofiled-* (%lu)\n" - buffer->AppendString("# total (", 0); - buffer->AppendUnsignedLong(all_total.committed_bytes(), 0); - buffer->AppendString(") ", 0); - buffer->AppendChar(all_total.committed_bytes() == - profiled_mmap_.committed_bytes() + - unhooked_total.committed_bytes() ? '=' : '!'); - buffer->AppendString("= profiled-mmap (", 0); - buffer->AppendUnsignedLong(profiled_mmap_.committed_bytes(), 0); - buffer->AppendString(") + nonprofiled-* (", 0); - buffer->AppendUnsignedLong(unhooked_total.committed_bytes(), 0); - buffer->AppendString(")\n", 0); - - // " virtual committed" - buffer->AppendString("", 26); - buffer->AppendString(kVirtualLabel, 12); - buffer->AppendChar(' '); - buffer->AppendString(kCommittedLabel, 12); - buffer->AppendString("\n", 0); - - all_total.Unparse("total", buffer); - all_[ABSENT].Unparse("absent", buffer); - all_[FILE_EXEC].Unparse("file-exec", buffer); - all_[FILE_NONEXEC].Unparse("file-nonexec", buffer); - all_[ANONYMOUS].Unparse("anonymous", buffer); - all_[STACK].Unparse("stack", buffer); - all_[OTHER].Unparse("other", buffer); - unhooked_total.Unparse("nonprofiled-total", buffer); - unhooked_[ABSENT].Unparse("nonprofiled-absent", buffer); - unhooked_[ANONYMOUS].Unparse("nonprofiled-anonymous", buffer); - unhooked_[FILE_EXEC].Unparse("nonprofiled-file-exec", buffer); - unhooked_[FILE_NONEXEC].Unparse("nonprofiled-file-nonexec", buffer); - unhooked_[STACK].Unparse("nonprofiled-stack", buffer); - unhooked_[OTHER].Unparse("nonprofiled-other", buffer); - profiled_mmap_.Unparse("profiled-mmap", buffer); - profiled_malloc_.Unparse("profiled-malloc", buffer); -} - -// static -void DeepHeapProfile::GlobalStats::RecordAlloc(const void* pointer, - AllocValue* alloc_value, - DeepHeapProfile* deep_profile) { - uint64 address = reinterpret_cast<uintptr_t>(pointer); - size_t committed = deep_profile->memory_residence_info_getter_->CommittedSize( - address, address + alloc_value->bytes - 1, NULL); - - DeepBucket* deep_bucket = deep_profile->deep_table_.Lookup( - alloc_value->bucket(), -#if defined(TYPE_PROFILING) - LookupType(pointer), -#endif - /* is_mmap */ false); - deep_bucket->committed_size += committed; - deep_profile->stats_.profiled_malloc_.AddToVirtualBytes(alloc_value->bytes); - deep_profile->stats_.profiled_malloc_.AddToCommittedBytes(committed); -} - -DeepHeapProfile::DeepBucket* - DeepHeapProfile::GlobalStats::GetInformationOfMemoryRegion( - const MemoryRegionMap::RegionIterator& mmap_iter, - const MemoryResidenceInfoGetterInterface* memory_residence_info_getter, - DeepHeapProfile* deep_profile) { - size_t committed = deep_profile->memory_residence_info_getter_-> - CommittedSize(mmap_iter->start_addr, mmap_iter->end_addr - 1, NULL); - - // TODO(dmikurube): Store a reference to the bucket in region. - Bucket* bucket = MemoryRegionMap::GetBucket( - mmap_iter->call_stack_depth, mmap_iter->call_stack); - DeepBucket* deep_bucket = NULL; - if (bucket != NULL) { - deep_bucket = deep_profile->deep_table_.Lookup( - bucket, -#if defined(TYPE_PROFILING) - NULL, // No type information for memory regions by mmap. -#endif - /* is_mmap */ true); - if (deep_bucket != NULL) - deep_bucket->committed_size += committed; - } - - profiled_mmap_.AddToVirtualBytes( - mmap_iter->end_addr - mmap_iter->start_addr); - profiled_mmap_.AddToCommittedBytes(committed); - - return deep_bucket; -} - -// static -void DeepHeapProfile::WriteProcMaps(const char* prefix, - char raw_buffer[], - int buffer_size) { - char filename[100]; - snprintf(filename, sizeof(filename), - "%s.%05d.maps", prefix, static_cast<int>(getpid())); - - RawFD fd = RawOpenForWriting(filename); - RAW_DCHECK(fd != kIllegalRawFD, ""); - - int length; - bool wrote_all; - length = tcmalloc::FillProcSelfMaps(raw_buffer, buffer_size, &wrote_all); - RAW_DCHECK(wrote_all, ""); - RAW_DCHECK(length <= buffer_size, ""); - RawWrite(fd, raw_buffer, length); - RawClose(fd); -} -#else // USE_DEEP_HEAP_PROFILE - -DeepHeapProfile::DeepHeapProfile(HeapProfileTable* heap_profile, - const char* prefix, - enum PageFrameType pageframe_type) - : heap_profile_(heap_profile) { -} - -DeepHeapProfile::~DeepHeapProfile() { -} - -void DeepHeapProfile::DumpOrderedProfile(const char* reason, - char raw_buffer[], - int buffer_size, - RawFD fd) { -} - -#endif // USE_DEEP_HEAP_PROFILE diff --git a/third_party/tcmalloc/chromium/src/deep-heap-profile.h b/third_party/tcmalloc/chromium/src/deep-heap-profile.h deleted file mode 100644 index 0544b31..0000000 --- a/third_party/tcmalloc/chromium/src/deep-heap-profile.h +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// --- -// Author: Sainbayar Sukhbaatar -// Dai Mikurube -// -// This file contains a class DeepHeapProfile and its public function -// DeepHeapProfile::DumpOrderedProfile(). The function works like -// HeapProfileTable::FillOrderedProfile(), but dumps directory to files. -// -// DeepHeapProfile::DumpOrderedProfile() dumps more detailed information about -// heap usage, which includes OS-level information such as memory residency and -// type information if the type profiler is available. -// -// DeepHeapProfile::DumpOrderedProfile() uses data stored in HeapProfileTable. -// Any code in DeepHeapProfile runs only when DumpOrderedProfile() is called. -// It has overhead in dumping, but no overhead in logging. -// -// It currently works only on Linux including Android. It does nothing in -// non-Linux environments. - -// Note that uint64 is used to represent addresses instead of uintptr_t, and -// int is used to represent buffer sizes instead of size_t. -// It's for consistency with other TCMalloc functions. ProcMapsIterator uses -// uint64 for addresses, and HeapProfileTable::DumpOrderedProfile uses int -// for buffer sizes. - -#ifndef BASE_DEEP_HEAP_PROFILE_H_ -#define BASE_DEEP_HEAP_PROFILE_H_ - -#include "config.h" - -#if defined(TYPE_PROFILING) -#include <typeinfo> -#endif - -#if defined(__linux__) || defined(_WIN32) || defined(_WIN64) -#define USE_DEEP_HEAP_PROFILE 1 -#endif - -#include "addressmap-inl.h" -#include "heap-profile-table.h" -#include "memory_region_map.h" - -class DeepHeapProfile { - public: - enum PageFrameType { - DUMP_NO_PAGEFRAME = 0, // Dumps nothing about pageframes - DUMP_PFN = 1, // Dumps only pageframe numbers (PFNs) - DUMP_PAGECOUNT = 2, // Dumps PFNs and pagecounts - }; - - // Constructs a DeepHeapProfile instance. It works as a wrapper of - // HeapProfileTable. - // - // |heap_profile| is a pointer to HeapProfileTable. DeepHeapProfile reads - // data in |heap_profile| and forwards operations to |heap_profile| if - // DeepHeapProfile is not available (non-Linux). - // |prefix| is a prefix of dumped file names. - // |pageframe_type| means what information is dumped for pageframes. - DeepHeapProfile(HeapProfileTable* heap_profile, - const char* prefix, - enum PageFrameType pageframe_type); - ~DeepHeapProfile(); - - // Dumps a deep profile into |fd| with using |raw_buffer| of |buffer_size|. - // - // In addition, a list of buckets is dumped into a ".buckets" file in - // descending order of allocated bytes. - void DumpOrderedProfile(const char* reason, - char raw_buffer[], - int buffer_size, - RawFD fd); - - private: -#ifdef USE_DEEP_HEAP_PROFILE - typedef HeapProfileTable::Stats Stats; - typedef HeapProfileTable::Bucket Bucket; - typedef HeapProfileTable::AllocValue AllocValue; - typedef HeapProfileTable::AllocationMap AllocationMap; - - enum MapsRegionType { - // Bytes of memory which were not recognized with /proc/<pid>/maps. - // This size should be 0. - ABSENT, - - // Bytes of memory which is mapped anonymously. - // Regions which contain nothing in the last column of /proc/<pid>/maps. - ANONYMOUS, - - // Bytes of memory which is mapped to a executable/non-executable file. - // Regions which contain file paths in the last column of /proc/<pid>/maps. - FILE_EXEC, - FILE_NONEXEC, - - // Bytes of memory which is labeled [stack] in /proc/<pid>/maps. - STACK, - - // Bytes of memory which is labeled, but not mapped to any file. - // Regions which contain non-path strings in the last column of - // /proc/<pid>/maps. - OTHER, - - NUMBER_OF_MAPS_REGION_TYPES - }; - - static const char* kMapsRegionTypeDict[NUMBER_OF_MAPS_REGION_TYPES]; - - // Manages a buffer to keep a text to be dumped to a file. - class TextBuffer { - public: - TextBuffer(char *raw_buffer, int size, RawFD fd) - : buffer_(raw_buffer), - size_(size), - cursor_(0), - fd_(fd) { - } - - int Size(); - int FilledBytes(); - void Clear(); - void Flush(); - - bool AppendChar(char value); - bool AppendString(const char* value, int width); - bool AppendInt(int value, int width, bool leading_zero); - bool AppendLong(long value, int width); - bool AppendUnsignedLong(unsigned long value, int width); - bool AppendInt64(int64 value, int width); - bool AppendBase64(uint64 value, int width); - bool AppendPtr(uint64 value, int width); - - private: - bool ForwardCursor(int appended); - - char *buffer_; - int size_; - int cursor_; - RawFD fd_; - DISALLOW_COPY_AND_ASSIGN(TextBuffer); - }; - - // Defines an interface for getting info about memory residence. - class MemoryResidenceInfoGetterInterface { - public: - virtual ~MemoryResidenceInfoGetterInterface(); - - // Initializes the instance. - virtual void Initialize() = 0; - - // Returns the number of resident (including swapped) bytes of the given - // memory region from |first_address| to |last_address| inclusive. - virtual size_t CommittedSize(uint64 first_address, - uint64 last_address, - TextBuffer* buffer) const = 0; - - // Creates a new platform specific MemoryResidenceInfoGetterInterface. - static MemoryResidenceInfoGetterInterface* Create( - PageFrameType pageframe_type); - - virtual bool IsPageCountAvailable() const = 0; - - protected: - MemoryResidenceInfoGetterInterface(); - }; - -#if defined(_WIN32) || defined(_WIN64) - // TODO(peria): Implement this class. - class MemoryInfoGetterWindows : public MemoryResidenceInfoGetterInterface { - public: - MemoryInfoGetterWindows(PageFrameType) {} - virtual ~MemoryInfoGetterWindows() {} - - virtual void Initialize(); - - virtual size_t CommittedSize(uint64 first_address, - uint64 last_address, - TextBuffer* buffer) const; - - virtual bool IsPageCountAvailable() const; - }; -#endif // defined(_WIN32) || defined(_WIN64) - -#if defined(__linux__) - // Implements MemoryResidenceInfoGetterInterface for Linux. - class MemoryInfoGetterLinux : public MemoryResidenceInfoGetterInterface { - public: - MemoryInfoGetterLinux(PageFrameType pageframe_type) - : pageframe_type_(pageframe_type), - pagemap_fd_(kIllegalRawFD), - kpagecount_fd_(kIllegalRawFD) {} - virtual ~MemoryInfoGetterLinux() {} - - // Opens /proc/<pid>/pagemap and stores its file descriptor. - // It keeps open while the process is running. - // - // Note that file descriptors need to be refreshed after fork. - virtual void Initialize(); - - // Returns the number of resident (including swapped) bytes of the given - // memory region from |first_address| to |last_address| inclusive. - virtual size_t CommittedSize(uint64 first_address, - uint64 last_address, - TextBuffer* buffer) const; - - virtual bool IsPageCountAvailable() const; - - private: - struct State { - uint64 pfn; - bool is_committed; // Currently, we use only this - bool is_present; - bool is_swapped; - bool is_shared; - bool is_mmap; - }; - - uint64 ReadPageCount(uint64 pfn) const; - - // Seeks to the offset of the open pagemap file. - // It returns true if succeeded. - bool Seek(uint64 address) const; - - // Reads a pagemap state from the current offset. - // It returns true if succeeded. - bool Read(State* state, bool get_pfn) const; - - PageFrameType pageframe_type_; - RawFD pagemap_fd_; - RawFD kpagecount_fd_; - }; -#endif // defined(__linux__) - - // Contains extended information for HeapProfileTable::Bucket. These objects - // are managed in a hash table (DeepBucketTable) whose key is an address of - // a Bucket and other additional information. - struct DeepBucket { - public: - void UnparseForStats(TextBuffer* buffer); - void UnparseForBucketFile(TextBuffer* buffer); - - Bucket* bucket; -#if defined(TYPE_PROFILING) - const std::type_info* type; // A type of the object -#endif - size_t committed_size; // A resident size of this bucket - bool is_mmap; // True if the bucket represents a mmap region - int id; // A unique ID of the bucket - bool is_logged; // True if the stracktrace is logged to a file - DeepBucket* next; // A reference to the next entry in the hash table - }; - - // Manages a hash table for DeepBucket. - class DeepBucketTable { - public: - DeepBucketTable(int size, - HeapProfileTable::Allocator alloc, - HeapProfileTable::DeAllocator dealloc); - ~DeepBucketTable(); - - // Finds a DeepBucket instance corresponding to the given |bucket|, or - // creates a new DeepBucket object if it doesn't exist. - DeepBucket* Lookup(Bucket* bucket, -#if defined(TYPE_PROFILING) - const std::type_info* type, -#endif - bool is_mmap); - - // Writes stats of the hash table to |buffer| for DumpOrderedProfile. - void UnparseForStats(TextBuffer* buffer); - - // Writes all buckets for a bucket file with using |buffer|. - void WriteForBucketFile(const char* prefix, - int dump_count, - char raw_buffer[], - int buffer_size); - - // Resets 'committed_size' members in DeepBucket objects. - void ResetCommittedSize(); - - // Resets all 'is_loggeed' flags in DeepBucket objects. - void ResetIsLogged(); - - private: - // Adds |add| to a |hash_value| for Lookup. - inline static void AddToHashValue(uintptr_t add, uintptr_t* hash_value); - inline static void FinishHashValue(uintptr_t* hash_value); - - DeepBucket** table_; - size_t table_size_; - HeapProfileTable::Allocator alloc_; - HeapProfileTable::DeAllocator dealloc_; - int bucket_id_; - }; - - class RegionStats { - public: - RegionStats(): virtual_bytes_(0), committed_bytes_(0) {} - ~RegionStats() {} - - // Initializes 'virtual_bytes_' and 'committed_bytes_'. - void Initialize(); - - // Updates itself to contain the tallies of 'virtual_bytes' and - // 'committed_bytes' in the region from |first_adress| to |last_address| - // inclusive. - uint64 Record( - const MemoryResidenceInfoGetterInterface* memory_residence_info_getter, - uint64 first_address, - uint64 last_address, - TextBuffer* buffer); - - // Writes stats of the region into |buffer| with |name|. - void Unparse(const char* name, TextBuffer* buffer); - - size_t virtual_bytes() const { return virtual_bytes_; } - size_t committed_bytes() const { return committed_bytes_; } - void AddToVirtualBytes(size_t additional_virtual_bytes) { - virtual_bytes_ += additional_virtual_bytes; - } - void AddToCommittedBytes(size_t additional_committed_bytes) { - committed_bytes_ += additional_committed_bytes; - } - void AddAnotherRegionStat(const RegionStats& other) { - virtual_bytes_ += other.virtual_bytes_; - committed_bytes_ += other.committed_bytes_; - } - - private: - size_t virtual_bytes_; - size_t committed_bytes_; - DISALLOW_COPY_AND_ASSIGN(RegionStats); - }; - - class GlobalStats { - public: - // Snapshots and calculates global stats from /proc/<pid>/maps and pagemap. - void SnapshotMaps( - const MemoryResidenceInfoGetterInterface* memory_residence_info_getter, - DeepHeapProfile* deep_profile, - TextBuffer* mmap_dump_buffer); - - // Snapshots allocations by malloc and mmap. - void SnapshotAllocations(DeepHeapProfile* deep_profile); - - // Writes global stats into |buffer|. - void Unparse(TextBuffer* buffer); - - private: - // Records both virtual and committed byte counts of malloc and mmap regions - // as callback functions for AllocationMap::Iterate(). - static void RecordAlloc(const void* pointer, - AllocValue* alloc_value, - DeepHeapProfile* deep_profile); - - DeepBucket* GetInformationOfMemoryRegion( - const MemoryRegionMap::RegionIterator& mmap_iter, - const MemoryResidenceInfoGetterInterface* memory_residence_info_getter, - DeepHeapProfile* deep_profile); - - // All RegionStats members in this class contain the bytes of virtual - // memory and committed memory. - // TODO(dmikurube): These regions should be classified more precisely later - // for more detailed analysis. - RegionStats all_[NUMBER_OF_MAPS_REGION_TYPES]; - - RegionStats unhooked_[NUMBER_OF_MAPS_REGION_TYPES]; - - // Total bytes of malloc'ed regions. - RegionStats profiled_malloc_; - - // Total bytes of mmap'ed regions. - RegionStats profiled_mmap_; - }; - - // Writes reformatted /proc/<pid>/maps into a file "|prefix|.<pid>.maps" - // with using |raw_buffer| of |buffer_size|. - static void WriteProcMaps(const char* prefix, - char raw_buffer[], - int buffer_size); - - // Appends the command line (/proc/pid/cmdline on Linux) into |buffer|. - bool AppendCommandLine(TextBuffer* buffer); - - MemoryResidenceInfoGetterInterface* memory_residence_info_getter_; - - // Process ID of the last dump. This can change by fork. - pid_t most_recent_pid_; - - GlobalStats stats_; // Stats about total memory. - int dump_count_; // The number of dumps. - char* filename_prefix_; // Output file prefix. - char run_id_[128]; - - DeepBucketTable deep_table_; - - enum PageFrameType pageframe_type_; -#endif // USE_DEEP_HEAP_PROFILE - - HeapProfileTable* heap_profile_; - - DISALLOW_COPY_AND_ASSIGN(DeepHeapProfile); -}; - -#endif // BASE_DEEP_HEAP_PROFILE_H_ diff --git a/third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h b/third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h deleted file mode 100644 index 1236258..0000000 --- a/third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TYPE_PROFILER_MAP_H_ -#define TYPE_PROFILER_MAP_H_ - -#if defined(TYPE_PROFILING) - -#include <typeinfo> - -// PERFTOOLS_DLL_DECL is unnecessary, as it is Windows specific. - -void InsertType(void* address, size_t size, const std::type_info& type); -void EraseType(void* address); -const std::type_info* LookupType(const void* address); - -#endif // defined(TYPE_PROFILING) - -#endif // TYPE_PROFILER_MAP_H_ diff --git a/third_party/tcmalloc/chromium/src/heap-profile-table.cc b/third_party/tcmalloc/chromium/src/heap-profile-table.cc index 1e0eea5..985ea20 100644 --- a/third_party/tcmalloc/chromium/src/heap-profile-table.cc +++ b/third_party/tcmalloc/chromium/src/heap-profile-table.cc @@ -92,9 +92,6 @@ DEFINE_int32(heap_check_max_leaks, // header of the dumped heap profile static const char kProfileHeader[] = "heap profile: "; static const char kProcSelfMapsHeader[] = "\nMAPPED_LIBRARIES:\n"; -#if defined(TYPE_PROFILING) -static const char kTypeProfileStatsHeader[] = "type statistics:\n"; -#endif // defined(TYPE_PROFILING) //---------------------------------------------------------------------- @@ -361,29 +358,6 @@ void HeapProfileTable::DumpMarkedObjects(AllocationMark mark, RawClose(fd); } -#if defined(TYPE_PROFILING) -void HeapProfileTable::DumpTypeStatistics(const char* file_name) const { - RawFD fd = RawOpenForWriting(file_name); - if (fd == kIllegalRawFD) { - RAW_LOG(ERROR, "Failed dumping type statistics to %s", file_name); - return; - } - - AddressMap<TypeCount>* type_size_map; - type_size_map = new(alloc_(sizeof(AddressMap<TypeCount>))) - AddressMap<TypeCount>(alloc_, dealloc_); - address_map_->Iterate(TallyTypesItererator, type_size_map); - - RawWrite(fd, kTypeProfileStatsHeader, strlen(kTypeProfileStatsHeader)); - const DumpArgs args(fd, NULL); - type_size_map->Iterate<const DumpArgs&>(DumpTypesIterator, args); - RawClose(fd); - - type_size_map->~AddressMap<TypeCount>(); - dealloc_(type_size_map); -} -#endif // defined(TYPE_PROFILING) - void HeapProfileTable::IterateOrderedAllocContexts( AllocContextIterator callback) const { Bucket** list = MakeSortedBucketList(); @@ -451,41 +425,6 @@ void HeapProfileTable::DumpBucketIterator(const Bucket* bucket, "", NULL); } -#if defined(TYPE_PROFILING) -// static -void HeapProfileTable::TallyTypesItererator( - const void* ptr, - AllocValue* value, - AddressMap<TypeCount>* type_size_map) { - const std::type_info* type = LookupType(ptr); - - const void* key = NULL; - if (type) - key = type->name(); - - TypeCount* count = type_size_map->FindMutable(key); - if (count) { - count->bytes += value->bytes; - ++count->objects; - } else { - type_size_map->Insert(key, TypeCount(value->bytes, 1)); - } -} - -// static -void HeapProfileTable::DumpTypesIterator(const void* ptr, - TypeCount* count, - const DumpArgs& args) { - char buf[1024]; - int len; - const char* mangled_type_name = static_cast<const char*>(ptr); - len = snprintf(buf, sizeof(buf), "%6d: %8" PRId64 " @ %s\n", - count->objects, count->bytes, - mangled_type_name ? mangled_type_name : "(no_typeinfo)"); - RawWrite(args.fd, buf, len); -} -#endif // defined(TYPE_PROFILING) - inline void HeapProfileTable::DumpNonLiveIterator(const void* ptr, AllocValue* v, const DumpArgs& args) { diff --git a/third_party/tcmalloc/chromium/src/heap-profile-table.h b/third_party/tcmalloc/chromium/src/heap-profile-table.h index c2ad39f..b0c3695 100644 --- a/third_party/tcmalloc/chromium/src/heap-profile-table.h +++ b/third_party/tcmalloc/chromium/src/heap-profile-table.h @@ -40,10 +40,6 @@ #include "base/logging.h" // for RawFD #include "heap-profile-stats.h" -#if defined(TYPE_PROFILING) -#include <gperftools/type_profiler_map.h> -#endif // defined(TYPE_PROFILING) - // Table to maintain a heap profile data inside, // i.e. the set of currently active heap memory allocations. // thread-unsafe and non-reentrant code: @@ -223,13 +219,7 @@ class HeapProfileTable { // used for leak checking (using HeapLeakChecker). void DumpMarkedObjects(AllocationMark mark, const char* file_name); -#if defined(TYPE_PROFILING) - void DumpTypeStatistics(const char* file_name) const; -#endif // defined(TYPE_PROFILING) - private: - friend class DeepHeapProfile; - // data types ---------------------------- // Hash table bucket to hold (de)allocation stats @@ -328,18 +318,6 @@ class HeapProfileTable { // mark unmarked allocations. }; -#if defined(TYPE_PROFILING) - struct TypeCount { - TypeCount(size_t bytes_arg, unsigned int objects_arg) - : bytes(bytes_arg), - objects(objects_arg) { - } - - size_t bytes; - unsigned int objects; - }; -#endif // defined(TYPE_PROFILING) - struct AllocationAddressIteratorArgs { AllocationAddressIteratorArgs(AddressIterator callback_arg, void* data_arg) : callback(callback_arg), @@ -409,16 +387,6 @@ class HeapProfileTable { inline static void DumpMarkedIterator(const void* ptr, AllocValue* v, const DumpMarkedArgs& args); -#if defined(TYPE_PROFILING) - inline static void TallyTypesItererator(const void* ptr, - AllocValue* value, - AddressMap<TypeCount>* type_size_map); - - inline static void DumpTypesIterator(const void* ptr, - TypeCount* size, - const DumpArgs& args); -#endif // defined(TYPE_PROFILING) - // 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. diff --git a/third_party/tcmalloc/chromium/src/heap-profiler.cc b/third_party/tcmalloc/chromium/src/heap-profiler.cc index 46a81a4..43a6f35 100644 --- a/third_party/tcmalloc/chromium/src/heap-profiler.cc +++ b/third_party/tcmalloc/chromium/src/heap-profiler.cc @@ -68,7 +68,6 @@ #include "base/spinlock.h" #include "base/low_level_alloc.h" #include "base/sysinfo.h" // for GetUniquePathFromEnv() -#include "deep-heap-profile.h" #include "heap-profile-table.h" #include "memory_region_map.h" @@ -81,38 +80,6 @@ #endif #endif -#if defined(__ANDROID__) || defined(ANDROID) -// On android, there are no environment variables. -// Instead, we use system properties, set via: -// adb shell setprop prop_name prop_value -// From <sys/system_properties.h>, -// PROP_NAME_MAX 32 -// PROP_VALUE_MAX 92 -#define HEAPPROFILE "heapprof" -#define HEAP_PROFILE_ALLOCATION_INTERVAL "heapprof.allocation_interval" -#define HEAP_PROFILE_DEALLOCATION_INTERVAL "heapprof.deallocation_interval" -#define HEAP_PROFILE_INUSE_INTERVAL "heapprof.inuse_interval" -#define HEAP_PROFILE_TIME_INTERVAL "heapprof.time_interval" -#define HEAP_PROFILE_MMAP_LOG "heapprof.mmap_log" -#define HEAP_PROFILE_MMAP "heapprof.mmap" -#define HEAP_PROFILE_ONLY_MMAP "heapprof.only_mmap" -#define DEEP_HEAP_PROFILE "heapprof.deep_heap_profile" -#define DEEP_HEAP_PROFILE_PAGEFRAME "heapprof.deep.pageframe" -#define HEAP_PROFILE_TYPE_STATISTICS "heapprof.type_statistics" -#else // defined(__ANDROID__) || defined(ANDROID) -#define HEAPPROFILE "HEAPPROFILE" -#define HEAP_PROFILE_ALLOCATION_INTERVAL "HEAP_PROFILE_ALLOCATION_INTERVAL" -#define HEAP_PROFILE_DEALLOCATION_INTERVAL "HEAP_PROFILE_DEALLOCATION_INTERVAL" -#define HEAP_PROFILE_INUSE_INTERVAL "HEAP_PROFILE_INUSE_INTERVAL" -#define HEAP_PROFILE_TIME_INTERVAL "HEAP_PROFILE_TIME_INTERVAL" -#define HEAP_PROFILE_MMAP_LOG "HEAP_PROFILE_MMAP_LOG" -#define HEAP_PROFILE_MMAP "HEAP_PROFILE_MMAP" -#define HEAP_PROFILE_ONLY_MMAP "HEAP_PROFILE_ONLY_MMAP" -#define DEEP_HEAP_PROFILE "DEEP_HEAP_PROFILE" -#define DEEP_HEAP_PROFILE_PAGEFRAME "DEEP_HEAP_PROFILE_PAGEFRAME" -#define HEAP_PROFILE_TYPE_STATISTICS "HEAP_PROFILE_TYPE_STATISTICS" -#endif // defined(__ANDROID__) || defined(ANDROID) - using STL_NAMESPACE::string; using STL_NAMESPACE::sort; @@ -154,20 +121,6 @@ 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"); -DEFINE_bool(deep_heap_profile, - EnvToBool(DEEP_HEAP_PROFILE, false), - "If heap-profiling is on, profile deeper (Linux and Android)"); -DEFINE_int32(deep_heap_profile_pageframe, - EnvToInt(DEEP_HEAP_PROFILE_PAGEFRAME, 0), - "Needs deeper profile. If 1, dump page frame numbers (PFNs). " - "If 2, dump page counts (/proc/kpagecount) with PFNs."); -#if defined(TYPE_PROFILING) -DEFINE_bool(heap_profile_type_statistics, - EnvToBool(HEAP_PROFILE_TYPE_STATISTICS, false), - "If heap-profiling is on, dump type statistics."); -#endif // defined(TYPE_PROFILING) - - //---------------------------------------------------------------------- // Locking //---------------------------------------------------------------------- @@ -220,7 +173,6 @@ 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 -static DeepHeapProfile* deep_profile = NULL; // deep memory profiler // Callback to generate a stack trace for an allocation. May be overriden // by an application to provide its own pseudo-stacks. @@ -301,25 +253,11 @@ static void DumpProfileLocked(const char* reason) { reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); } - if (deep_profile) { - deep_profile->DumpOrderedProfile(reason, global_profiler_buffer, - kProfileBufferSize, fd); - } else { - char* profile = DoGetHeapProfileLocked(global_profiler_buffer, - kProfileBufferSize); - RawWrite(fd, profile, strlen(profile)); - } + char* profile = DoGetHeapProfileLocked(global_profiler_buffer, + kProfileBufferSize); + RawWrite(fd, profile, strlen(profile)); RawClose(fd); -#if defined(TYPE_PROFILING) - if (FLAGS_heap_profile_type_statistics) { - snprintf(file_name, sizeof(file_name), "%s.%05d.%04d.type", - filename_prefix, getpid(), dump_count); - RAW_VLOG(0, "Dumping type statistics to %s", file_name); - heap_profile->DumpTypeStatistics(file_name); - } -#endif // defined(TYPE_PROFILING) - dumping = false; } @@ -529,14 +467,6 @@ extern "C" void HeapProfilerStart(const char* prefix) { high_water_mark = 0; last_dump_time = 0; - if (FLAGS_deep_heap_profile) { - // Initialize deep memory profiler - RAW_VLOG(0, "[%d] Starting a deep memory profiler", getpid()); - deep_profile = new(ProfilerMalloc(sizeof(DeepHeapProfile))) - DeepHeapProfile(heap_profile, prefix, DeepHeapProfile::PageFrameType( - FLAGS_deep_heap_profile_pageframe)); - } - // We do not reset dump_count so if the user does a sequence of // HeapProfilerStart/HeapProfileStop, we will get a continuous // sequence of profiles. @@ -598,13 +528,6 @@ extern "C" void HeapProfilerStop() { RAW_CHECK(MallocHook::RemoveMunmapHook(&MunmapHook), ""); } - if (deep_profile) { - // free deep memory profiler - deep_profile->~DeepHeapProfile(); - ProfilerFree(deep_profile); - deep_profile = NULL; - } - // free profile heap_profile->~HeapProfileTable(); ProfilerFree(heap_profile); diff --git a/third_party/tcmalloc/chromium/src/type_profiler_map.cc b/third_party/tcmalloc/chromium/src/type_profiler_map.cc deleted file mode 100644 index a2f21f8..0000000 --- a/third_party/tcmalloc/chromium/src/type_profiler_map.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#if defined(TYPE_PROFILING) - -#include <config.h> - -#include <new> -#include <stddef.h> -#include <typeinfo> - -#include <gperftools/type_profiler_map.h> - -#include "addressmap-inl.h" -#include "base/logging.h" -#include "base/low_level_alloc.h" -#include "base/spinlock.h" -#include "tcmalloc_guard.h" - -namespace { - -const TCMallocGuard tcmalloc_initializer; - -//---------------------------------------------------------------------- -// A struct to store size and type_info of an object -//---------------------------------------------------------------------- - -struct ObjectInfo { - public: - ObjectInfo(): size(0), type(NULL) {} - ObjectInfo(size_t size_arg, const std::type_info* type_arg) - : size(size_arg), - type(type_arg) { - } - - size_t size; - const std::type_info* type; -}; - -//---------------------------------------------------------------------- -// Locking -//---------------------------------------------------------------------- - -SpinLock g_type_profiler_lock(SpinLock::LINKER_INITIALIZED); - -//---------------------------------------------------------------------- -// Simple allocator for type_info map's internal memory -//---------------------------------------------------------------------- - -LowLevelAlloc::Arena* g_type_profiler_map_memory = NULL; - -void* TypeProfilerMalloc(size_t bytes) { - return LowLevelAlloc::AllocWithArena(bytes, g_type_profiler_map_memory); -} - -void TypeProfilerFree(void* p) { - LowLevelAlloc::Free(p); -} - -//---------------------------------------------------------------------- -// Profiling control/state data -//---------------------------------------------------------------------- - -AddressMap<ObjectInfo>* g_type_profiler_map = NULL; - -//---------------------------------------------------------------------- -// Manage type_info map -//---------------------------------------------------------------------- - -void InitializeTypeProfilerMemory() { - if (g_type_profiler_map_memory != NULL) { - RAW_DCHECK(g_type_profiler_map != NULL, "TypeProfilerMap is NULL"); - return; - } - - g_type_profiler_map_memory = - LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena()); - - g_type_profiler_map = - new(TypeProfilerMalloc(sizeof(*g_type_profiler_map))) - AddressMap<ObjectInfo>(TypeProfilerMalloc, TypeProfilerFree); -} - -} // namespace - -void InsertType(void* address, size_t size, const std::type_info& type) { - SpinLockHolder lock(&g_type_profiler_lock); - InitializeTypeProfilerMemory(); - - g_type_profiler_map->Insert(address, ObjectInfo(size, &type)); -} - -void EraseType(void* address) { - SpinLockHolder lock(&g_type_profiler_lock); - InitializeTypeProfilerMemory(); - - ObjectInfo obj; - g_type_profiler_map->FindAndRemove(address, &obj); -} - -const std::type_info* LookupType(const void* address) { - SpinLockHolder lock(&g_type_profiler_lock); - InitializeTypeProfilerMemory(); - - const ObjectInfo* found = g_type_profiler_map->Find(address); - if (found == NULL) - return NULL; - return found->type; -} - -#endif // defined(TYPE_PROFILING) |