Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: runtime/vm/malloc_hooks_test.cc

Issue 2680213002: Updated MallocHooks to collect stack traces when memory is allocated. (Closed)
Patch Set: Rebased and performed refactoring Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 6
7 #if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) 7 #if defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
8 8
9 #include "platform/assert.h" 9 #include "platform/assert.h"
10 #include "vm/class_finalizer.h"
11 #include "vm/globals.h" 10 #include "vm/globals.h"
12 #include "vm/malloc_hooks.h" 11 #include "vm/malloc_hooks.h"
13 #include "vm/symbols.h" 12 #include "vm/profiler.h"
13 #include "vm/profiler_service.h"
14 #include "vm/unit_test.h" 14 #include "vm/unit_test.h"
15 15
16 namespace dart { 16 namespace dart {
17 17
18 static void MallocHookTestBufferInitializer(volatile char* buffer, 18 static void MallocHookTestBufferInitializer(volatile char* buffer,
19 uintptr_t size) { 19 uintptr_t size) {
20 // Run through the buffer and do something. If we don't do this and the memory 20 // Run through the buffer and do something. If we don't do this and the memory
21 // in buffer isn't touched, the tcmalloc hooks won't be called. 21 // in buffer isn't touched, the tcmalloc hooks won't be called.
22 for (uintptr_t i = 0; i < size; ++i) { 22 for (uintptr_t i = 0; i < size; ++i) {
23 buffer[i] = i; 23 buffer[i] = i;
(...skipping 25 matching lines...) Expand all
49 MallocHooks::InitOnce(); 49 MallocHooks::InitOnce();
50 const intptr_t pre_hook_buffer_size = 3; 50 const intptr_t pre_hook_buffer_size = 3;
51 char* pre_hook_buffer = new char[pre_hook_buffer_size]; 51 char* pre_hook_buffer = new char[pre_hook_buffer_size];
52 MallocHookTestBufferInitializer(pre_hook_buffer, pre_hook_buffer_size); 52 MallocHookTestBufferInitializer(pre_hook_buffer, pre_hook_buffer_size);
53 53
54 MallocHooks::ResetStats(); 54 MallocHooks::ResetStats();
55 EXPECT_EQ(0L, MallocHooks::allocation_count()); 55 EXPECT_EQ(0L, MallocHooks::allocation_count());
56 EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes()); 56 EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes());
57 57
58 const intptr_t buffer_size = 10; 58 const intptr_t buffer_size = 10;
59 volatile char* buffer = new char[buffer_size]; 59 char* buffer = new char[buffer_size];
60 MallocHookTestBufferInitializer(buffer, buffer_size); 60 MallocHookTestBufferInitializer(buffer, buffer_size);
61 61
62 EXPECT_EQ(1L, MallocHooks::allocation_count()); 62 EXPECT_EQ(1L, MallocHooks::allocation_count());
63 EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size), 63 EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size),
64 MallocHooks::heap_allocated_memory_in_bytes()); 64 MallocHooks::heap_allocated_memory_in_bytes());
65 65
66 delete[] pre_hook_buffer; 66 delete[] pre_hook_buffer;
67 EXPECT_EQ(1L, MallocHooks::allocation_count()); 67 EXPECT_EQ(1L, MallocHooks::allocation_count());
68 EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size), 68 EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size),
69 MallocHooks::heap_allocated_memory_in_bytes()); 69 MallocHooks::heap_allocated_memory_in_bytes());
70 70
71 71
72 delete[] buffer; 72 delete[] buffer;
73 EXPECT_EQ(0L, MallocHooks::allocation_count()); 73 EXPECT_EQ(0L, MallocHooks::allocation_count());
74 EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes()); 74 EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes());
75 MallocHooks::TearDown(); 75 MallocHooks::TearDown();
76 } 76 }
77 77
78
79 VM_UNIT_TEST_CASE(StackTraceMallocHookSimpleTest) {
80 MallocHooks::ResetStats();
81 ASSERT(MallocHooks::ProfilingEnabled());
82
83 char* var = static_cast<char*>(malloc(16 * sizeof(char)));
84 Sample* sample = MallocHooks::GetSample(var);
85 EXPECT(sample != NULL);
86
87 free(var);
88 sample = MallocHooks::GetSample(var);
89 EXPECT(sample == NULL);
90 }
91
92
93 #if defined(TARGET_OS_WINDOWS)
94 __declspec(noinline) static uintptr_t GetProgramCounter() {
zra 2017/02/16 21:45:27 Use DART_NOINLINE defined in platform/globals.h.
bkonyi 2017/02/16 22:55:06 Yes, this was from vm/profiler.cc. I've moved the
95 return reinterpret_cast<uintptr_t>(_ReturnAddress());
96 }
97 #else
98 static uintptr_t __attribute__((noinline)) GetProgramCounter() {
99 return reinterpret_cast<uintptr_t>(
100 __builtin_extract_return_addr(__builtin_return_address(0)));
101 }
102 #endif
103
104
105 static char* __attribute__((noinline))
zra 2017/02/16 21:45:27 DART_NOINLINE
bkonyi 2017/02/16 22:55:06 Done.
106 StackTraceLengthHelper(uintptr_t* end_address) {
107 char* var = static_cast<char*>(malloc(16 * sizeof(char)));
108 *end_address = GetProgramCounter();
109 return var;
110 }
111
112
113 VM_UNIT_TEST_CASE(StackTraceMallocHookLengthTest) {
114 uintptr_t test_start_address =
115 reinterpret_cast<uintptr_t>(Dart_TestStackTraceMallocHookLengthTest);
116 uintptr_t helper_start_address =
117 reinterpret_cast<uintptr_t>(StackTraceLengthHelper);
118 uintptr_t helper_end_address = 0;
119
120 MallocHooks::ResetStats();
121 ASSERT(MallocHooks::ProfilingEnabled());
122
123 char* var = StackTraceLengthHelper(&helper_end_address);
124 Sample* sample = MallocHooks::GetSample(var);
125 EXPECT(sample != NULL);
126 uintptr_t test_end_address = GetProgramCounter();
127
128 uword address = sample->At(0);
129 EXPECT((helper_start_address <= address) && (helper_end_address >= address));
130 address = sample->At(1);
131 EXPECT((test_start_address <= address) && (test_end_address >= address));
132 free(var);
133 }
134
135
136 ISOLATE_UNIT_TEST_CASE(StackTraceMallocHookSimpleJSONTest) {
137 MallocHooks::ResetStats();
138 ASSERT(MallocHooks::ProfilingEnabled());
139 ClearProfileVisitor cpv(Isolate::Current());
140 Profiler::sample_buffer()->VisitSamples(&cpv);
141
142 char* var = static_cast<char*>(malloc(16 * sizeof(char)));
143 JSONStream js;
144 ProfilerService::PrintNativeAllocationJSON(&js, Profile::kNoTags, -1, -1);
145 const char* json = js.ToCString();
146
147 // Check that all the stack frames from the current down to main are actually
148 // present in the profile. This is just a simple sanity check to make sure
149 // that the ProfileTrie has a representation of the stack trace collected when
150 // var is allocated. More intense testing is already done in profiler_test.cc.
151 EXPECT_SUBSTRING("\"dart::Dart_TestStackTraceMallocHookSimpleJSONTest()\"",
152 json);
153 EXPECT_SUBSTRING("\"dart::TestCase::Run()\"", json);
154 EXPECT_SUBSTRING("\"dart::TestCaseBase::RunTest()\"", json);
155 EXPECT_SUBSTRING("\"main\"", json);
156
157 free(var);
158 }
159
78 }; // namespace dart 160 }; // namespace dart
79 161
80 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) 162 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
OLDNEW
« no previous file with comments | « runtime/vm/malloc_hooks.cc ('k') | runtime/vm/os_thread.h » ('j') | runtime/vm/profiler.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698