| Index: runtime/vm/malloc_hooks_test.cc
|
| diff --git a/runtime/vm/malloc_hooks_test.cc b/runtime/vm/malloc_hooks_test.cc
|
| index 791e2694aa9deff839b4454d2137c52575820a64..26a56478ae90d85fe7f9eaca17566e9d6bafdfaf 100644
|
| --- a/runtime/vm/malloc_hooks_test.cc
|
| +++ b/runtime/vm/malloc_hooks_test.cc
|
| @@ -4,13 +4,15 @@
|
|
|
| #include "platform/globals.h"
|
|
|
| -#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
|
| +#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && \
|
| + !defined(TARGET_ARCH_DBC) && !defined(TARGET_OS_FUCHSIA)
|
|
|
| #include "platform/assert.h"
|
| -#include "vm/class_finalizer.h"
|
| #include "vm/globals.h"
|
| #include "vm/malloc_hooks.h"
|
| -#include "vm/symbols.h"
|
| +#include "vm/os.h"
|
| +#include "vm/profiler.h"
|
| +#include "vm/profiler_service.h"
|
| #include "vm/unit_test.h"
|
|
|
| namespace dart {
|
| @@ -64,7 +66,7 @@ UNIT_TEST_CASE(FreeUnseenMemoryMallocHookTest) {
|
| EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes());
|
|
|
| const intptr_t buffer_size = 10;
|
| - volatile char* buffer = new char[buffer_size];
|
| + char* buffer = new char[buffer_size];
|
| MallocHookTestBufferInitializer(buffer, buffer_size);
|
|
|
| EXPECT_EQ(1L, MallocHooks::allocation_count());
|
| @@ -85,6 +87,123 @@ UNIT_TEST_CASE(FreeUnseenMemoryMallocHookTest) {
|
| FLAG_enable_malloc_hooks = enable_malloc_hooks_saved;
|
| }
|
|
|
| +
|
| +VM_UNIT_TEST_CASE(StackTraceMallocHookSimpleTest) {
|
| + bool enable_malloc_hooks_saved = FLAG_enable_malloc_hooks;
|
| + FLAG_enable_malloc_hooks = true;
|
| +
|
| + MallocHooks::InitOnce();
|
| + MallocHooks::ResetStats();
|
| +
|
| + bool enable_stack_traces_saved =
|
| + MallocHooks::stack_trace_collection_enabled();
|
| + MallocHooks::set_stack_trace_collection_enabled(true);
|
| +
|
| + char* var = static_cast<char*>(malloc(16 * sizeof(char)));
|
| + Sample* sample = MallocHooks::GetSample(var);
|
| + EXPECT(sample != NULL);
|
| +
|
| + free(var);
|
| + sample = MallocHooks::GetSample(var);
|
| + EXPECT(sample == NULL);
|
| + MallocHooks::TearDown();
|
| + MallocHooks::set_stack_trace_collection_enabled(enable_stack_traces_saved);
|
| + FLAG_enable_malloc_hooks = enable_malloc_hooks_saved;
|
| +}
|
| +
|
| +
|
| +static char* DART_NOINLINE StackTraceLengthHelper(uintptr_t* end_address) {
|
| + char* var = static_cast<char*>(malloc(16 * sizeof(char)));
|
| + *end_address = OS::GetProgramCounter();
|
| + return var;
|
| +}
|
| +
|
| +
|
| +VM_UNIT_TEST_CASE(StackTraceMallocHookLengthTest) {
|
| + bool enable_malloc_hooks_saved = FLAG_enable_malloc_hooks;
|
| + FLAG_enable_malloc_hooks = true;
|
| +
|
| + uintptr_t test_start_address =
|
| + reinterpret_cast<uintptr_t>(Dart_TestStackTraceMallocHookLengthTest);
|
| + uintptr_t helper_start_address =
|
| + reinterpret_cast<uintptr_t>(StackTraceLengthHelper);
|
| + uintptr_t helper_end_address = 0;
|
| +
|
| + MallocHooks::InitOnce();
|
| + MallocHooks::ResetStats();
|
| +
|
| + bool enable_stack_traces_saved =
|
| + MallocHooks::stack_trace_collection_enabled();
|
| + MallocHooks::set_stack_trace_collection_enabled(true);
|
| +
|
| + char* var = StackTraceLengthHelper(&helper_end_address);
|
| + Sample* sample = MallocHooks::GetSample(var);
|
| + EXPECT(sample != NULL);
|
| + uintptr_t test_end_address = OS::GetProgramCounter();
|
| +
|
| + // Ensure that all stack frames are where we expect them to be in the sample.
|
| + // If they aren't, the kSkipCount constant in malloc_hooks.cc is likely
|
| + // incorrect.
|
| + uword address = sample->At(0);
|
| + bool first_result =
|
| + (helper_start_address <= address) && (helper_end_address >= address);
|
| + EXPECT(first_result);
|
| + address = sample->At(1);
|
| + bool second_result =
|
| + (test_start_address <= address) && (test_end_address >= address);
|
| + EXPECT(second_result);
|
| +
|
| + if (!(first_result && second_result)) {
|
| + OS::PrintErr(
|
| + "If this test is failing, it's likely that the value set for"
|
| + "the number of frames to skip in malloc_hooks.cc is "
|
| + "incorrect for this configuration/platform. This value can be"
|
| + " found in malloc_hooks.cc in the AllocationInfo class, and "
|
| + "is stored in the kSkipCount constant.");
|
| + }
|
| +
|
| + free(var);
|
| + MallocHooks::TearDown();
|
| + MallocHooks::set_stack_trace_collection_enabled(enable_stack_traces_saved);
|
| + FLAG_enable_malloc_hooks = enable_malloc_hooks_saved;
|
| +}
|
| +
|
| +
|
| +ISOLATE_UNIT_TEST_CASE(StackTraceMallocHookSimpleJSONTest) {
|
| + bool enable_malloc_hooks_saved = FLAG_enable_malloc_hooks;
|
| + FLAG_enable_malloc_hooks = true;
|
| +
|
| + MallocHooks::InitOnce();
|
| + MallocHooks::ResetStats();
|
| +
|
| + bool enable_stack_traces_saved =
|
| + MallocHooks::stack_trace_collection_enabled();
|
| + MallocHooks::set_stack_trace_collection_enabled(true);
|
| +
|
| + ClearProfileVisitor cpv(Isolate::Current());
|
| + Profiler::sample_buffer()->VisitSamples(&cpv);
|
| +
|
| + char* var = static_cast<char*>(malloc(16 * sizeof(char)));
|
| + JSONStream js;
|
| + ProfilerService::PrintNativeAllocationJSON(&js, Profile::kNoTags, -1, -1);
|
| + const char* json = js.ToCString();
|
| +
|
| + // Check that all the stack frames from the current down to main are actually
|
| + // present in the profile. This is just a simple sanity check to make sure
|
| + // that the ProfileTrie has a representation of the stack trace collected when
|
| + // var is allocated. More intense testing is already done in profiler_test.cc.
|
| + EXPECT_SUBSTRING("\"dart::Dart_TestStackTraceMallocHookSimpleJSONTest()\"",
|
| + json);
|
| + EXPECT_SUBSTRING("\"dart::TestCase::Run()\"", json);
|
| + EXPECT_SUBSTRING("\"dart::TestCaseBase::RunTest()\"", json);
|
| + EXPECT_SUBSTRING("\"main\"", json);
|
| +
|
| + free(var);
|
| + MallocHooks::TearDown();
|
| + MallocHooks::set_stack_trace_collection_enabled(enable_stack_traces_saved);
|
| + FLAG_enable_malloc_hooks = enable_malloc_hooks_saved;
|
| +}
|
| +
|
| }; // namespace dart
|
|
|
| #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
|
|
|