| OLD | NEW | 
|    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     !defined(TARGET_ARCH_DBC) && !defined(TARGET_OS_FUCHSIA) | 
|    8  |    9  | 
|    9 #include "platform/assert.h" |   10 #include "platform/assert.h" | 
|   10 #include "vm/class_finalizer.h" |  | 
|   11 #include "vm/globals.h" |   11 #include "vm/globals.h" | 
|   12 #include "vm/malloc_hooks.h" |   12 #include "vm/malloc_hooks.h" | 
|   13 #include "vm/symbols.h" |   13 #include "vm/os.h" | 
 |   14 #include "vm/profiler.h" | 
 |   15 #include "vm/profiler_service.h" | 
|   14 #include "vm/unit_test.h" |   16 #include "vm/unit_test.h" | 
|   15  |   17  | 
|   16 namespace dart { |   18 namespace dart { | 
|   17  |   19  | 
|   18 static void MallocHookTestBufferInitializer(volatile char* buffer, |   20 static void MallocHookTestBufferInitializer(volatile char* buffer, | 
|   19                                             uintptr_t size) { |   21                                             uintptr_t size) { | 
|   20   // Run through the buffer and do something. If we don't do this and the memory |   22   // 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. |   23   // in buffer isn't touched, the tcmalloc hooks won't be called. | 
|   22   for (uintptr_t i = 0; i < size; ++i) { |   24   for (uintptr_t i = 0; i < size; ++i) { | 
|   23     buffer[i] = i; |   25     buffer[i] = i; | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
|   49   MallocHooks::InitOnce(); |   51   MallocHooks::InitOnce(); | 
|   50   const intptr_t pre_hook_buffer_size = 3; |   52   const intptr_t pre_hook_buffer_size = 3; | 
|   51   char* pre_hook_buffer = new char[pre_hook_buffer_size]; |   53   char* pre_hook_buffer = new char[pre_hook_buffer_size]; | 
|   52   MallocHookTestBufferInitializer(pre_hook_buffer, pre_hook_buffer_size); |   54   MallocHookTestBufferInitializer(pre_hook_buffer, pre_hook_buffer_size); | 
|   53  |   55  | 
|   54   MallocHooks::ResetStats(); |   56   MallocHooks::ResetStats(); | 
|   55   EXPECT_EQ(0L, MallocHooks::allocation_count()); |   57   EXPECT_EQ(0L, MallocHooks::allocation_count()); | 
|   56   EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes()); |   58   EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes()); | 
|   57  |   59  | 
|   58   const intptr_t buffer_size = 10; |   60   const intptr_t buffer_size = 10; | 
|   59   volatile char* buffer = new char[buffer_size]; |   61   char* buffer = new char[buffer_size]; | 
|   60   MallocHookTestBufferInitializer(buffer, buffer_size); |   62   MallocHookTestBufferInitializer(buffer, buffer_size); | 
|   61  |   63  | 
|   62   EXPECT_EQ(1L, MallocHooks::allocation_count()); |   64   EXPECT_EQ(1L, MallocHooks::allocation_count()); | 
|   63   EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size), |   65   EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size), | 
|   64             MallocHooks::heap_allocated_memory_in_bytes()); |   66             MallocHooks::heap_allocated_memory_in_bytes()); | 
|   65  |   67  | 
|   66   delete[] pre_hook_buffer; |   68   delete[] pre_hook_buffer; | 
|   67   EXPECT_EQ(1L, MallocHooks::allocation_count()); |   69   EXPECT_EQ(1L, MallocHooks::allocation_count()); | 
|   68   EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size), |   70   EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size), | 
|   69             MallocHooks::heap_allocated_memory_in_bytes()); |   71             MallocHooks::heap_allocated_memory_in_bytes()); | 
|   70  |   72  | 
|   71  |   73  | 
|   72   delete[] buffer; |   74   delete[] buffer; | 
|   73   EXPECT_EQ(0L, MallocHooks::allocation_count()); |   75   EXPECT_EQ(0L, MallocHooks::allocation_count()); | 
|   74   EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes()); |   76   EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes()); | 
|   75   MallocHooks::TearDown(); |   77   MallocHooks::TearDown(); | 
|   76 } |   78 } | 
|   77  |   79  | 
 |   80  | 
 |   81 VM_UNIT_TEST_CASE(StackTraceMallocHookSimpleTest) { | 
 |   82   bool stack_traces_enabled = MallocHooks::stack_trace_collection_enabled(); | 
 |   83   MallocHooks::set_stack_trace_collection_enabled(true); | 
 |   84  | 
 |   85   MallocHooks::ResetStats(); | 
 |   86   ASSERT(MallocHooks::ProfilingEnabled()); | 
 |   87  | 
 |   88   char* var = static_cast<char*>(malloc(16 * sizeof(char))); | 
 |   89   Sample* sample = MallocHooks::GetSample(var); | 
 |   90   EXPECT(sample != NULL); | 
 |   91  | 
 |   92   free(var); | 
 |   93   sample = MallocHooks::GetSample(var); | 
 |   94   EXPECT(sample == NULL); | 
 |   95   MallocHooks::set_stack_trace_collection_enabled(stack_traces_enabled); | 
 |   96 } | 
 |   97  | 
 |   98  | 
 |   99 static char* DART_NOINLINE StackTraceLengthHelper(uintptr_t* end_address) { | 
 |  100   char* var = static_cast<char*>(malloc(16 * sizeof(char))); | 
 |  101   *end_address = OS::GetProgramCounter(); | 
 |  102   return var; | 
 |  103 } | 
 |  104  | 
 |  105  | 
 |  106 VM_UNIT_TEST_CASE(StackTraceMallocHookLengthTest) { | 
 |  107   bool stack_traces_enabled = MallocHooks::stack_trace_collection_enabled(); | 
 |  108   MallocHooks::set_stack_trace_collection_enabled(true); | 
 |  109  | 
 |  110   uintptr_t test_start_address = | 
 |  111       reinterpret_cast<uintptr_t>(Dart_TestStackTraceMallocHookLengthTest); | 
 |  112   uintptr_t helper_start_address = | 
 |  113       reinterpret_cast<uintptr_t>(StackTraceLengthHelper); | 
 |  114   uintptr_t helper_end_address = 0; | 
 |  115  | 
 |  116   MallocHooks::ResetStats(); | 
 |  117   ASSERT(MallocHooks::ProfilingEnabled()); | 
 |  118  | 
 |  119   char* var = StackTraceLengthHelper(&helper_end_address); | 
 |  120   Sample* sample = MallocHooks::GetSample(var); | 
 |  121   EXPECT(sample != NULL); | 
 |  122   uintptr_t test_end_address = OS::GetProgramCounter(); | 
 |  123  | 
 |  124   // Ensure that all stack frames are where we expect them to be in the sample. | 
 |  125   // If they aren't, the kSkipCount constant in malloc_hooks.cc is likely | 
 |  126   // incorrect. | 
 |  127   uword address = sample->At(0); | 
 |  128   bool first_result = | 
 |  129       (helper_start_address <= address) && (helper_end_address >= address); | 
 |  130   EXPECT(first_result); | 
 |  131   address = sample->At(1); | 
 |  132   bool second_result = | 
 |  133       (test_start_address <= address) && (test_end_address >= address); | 
 |  134   EXPECT(second_result); | 
 |  135  | 
 |  136   if (!(first_result && second_result)) { | 
 |  137     OS::PrintErr( | 
 |  138         "If this test is failing, it's likely that the value set for" | 
 |  139         "the number of frames to skip in malloc_hooks.cc is " | 
 |  140         "incorrect for this configuration/platform. This value can be" | 
 |  141         " found in malloc_hooks.cc in the AllocationInfo class, and " | 
 |  142         "is stored in the kSkipCount constant."); | 
 |  143   } | 
 |  144  | 
 |  145   free(var); | 
 |  146   MallocHooks::set_stack_trace_collection_enabled(stack_traces_enabled); | 
 |  147 } | 
 |  148  | 
 |  149  | 
 |  150 ISOLATE_UNIT_TEST_CASE(StackTraceMallocHookSimpleJSONTest) { | 
 |  151   bool stack_traces_enabled = MallocHooks::stack_trace_collection_enabled(); | 
 |  152   MallocHooks::set_stack_trace_collection_enabled(true); | 
 |  153   MallocHooks::ResetStats(); | 
 |  154   ASSERT(MallocHooks::ProfilingEnabled()); | 
 |  155   ClearProfileVisitor cpv(Isolate::Current()); | 
 |  156   Profiler::sample_buffer()->VisitSamples(&cpv); | 
 |  157  | 
 |  158   char* var = static_cast<char*>(malloc(16 * sizeof(char))); | 
 |  159   JSONStream js; | 
 |  160   ProfilerService::PrintNativeAllocationJSON(&js, Profile::kNoTags, -1, -1); | 
 |  161   const char* json = js.ToCString(); | 
 |  162  | 
 |  163   // Check that all the stack frames from the current down to main are actually | 
 |  164   // present in the profile. This is just a simple sanity check to make sure | 
 |  165   // that the ProfileTrie has a representation of the stack trace collected when | 
 |  166   // var is allocated. More intense testing is already done in profiler_test.cc. | 
 |  167   EXPECT_SUBSTRING("\"dart::Dart_TestStackTraceMallocHookSimpleJSONTest()\"", | 
 |  168                    json); | 
 |  169   EXPECT_SUBSTRING("\"dart::TestCase::Run()\"", json); | 
 |  170   EXPECT_SUBSTRING("\"dart::TestCaseBase::RunTest()\"", json); | 
 |  171   EXPECT_SUBSTRING("\"main\"", json); | 
 |  172  | 
 |  173   free(var); | 
 |  174   MallocHooks::set_stack_trace_collection_enabled(stack_traces_enabled); | 
 |  175 } | 
 |  176  | 
|   78 };  // namespace dart |  177 };  // namespace dart | 
|   79  |  178  | 
|   80 #endif  // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) |  179 #endif  // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) | 
| OLD | NEW |