diff --git a/src/profiler/profiler-listener.cc b/src/profiler/profiler-listener.cc index 3269dfd81b..5199b61358 100644 --- a/src/profiler/profiler-listener.cc +++ b/src/profiler/profiler-listener.cc @@ -16,11 +16,7 @@ namespace internal { ProfilerListener::ProfilerListener(Isolate* isolate) : function_and_resource_names_(isolate->heap()) {} -ProfilerListener::~ProfilerListener() { - for (auto code_entry : code_entries_) { - delete code_entry; - } -} +ProfilerListener::~ProfilerListener() = default; void ProfilerListener::CallbackEvent(Name* name, Address entry_point) { CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); @@ -274,19 +270,23 @@ CodeEntry* ProfilerListener::NewCodeEntry( CodeEventListener::LogEventsAndTags tag, const char* name, const char* name_prefix, const char* resource_name, int line_number, int column_number, JITLineInfoTable* line_info, Address instruction_start) { - CodeEntry* code_entry = - new CodeEntry(tag, name, name_prefix, resource_name, line_number, - column_number, line_info, instruction_start); - code_entries_.push_back(code_entry); - return code_entry; + std::unique_ptr code_entry = base::make_unique( + tag, name, name_prefix, resource_name, line_number, column_number, + line_info, instruction_start); + CodeEntry* raw_code_entry = code_entry.get(); + code_entries_.push_back(std::move(code_entry)); + return raw_code_entry; } void ProfilerListener::AddObserver(CodeEventObserver* observer) { base::LockGuard guard(&mutex_); - if (std::find(observers_.begin(), observers_.end(), observer) != - observers_.end()) - return; - observers_.push_back(observer); + if (observers_.empty()) { + code_entries_.clear(); + } + if (std::find(observers_.begin(), observers_.end(), observer) == + observers_.end()) { + observers_.push_back(observer); + } } void ProfilerListener::RemoveObserver(CodeEventObserver* observer) { diff --git a/src/profiler/profiler-listener.h b/src/profiler/profiler-listener.h index e45544d278..c111bf81c4 100644 --- a/src/profiler/profiler-listener.h +++ b/src/profiler/profiler-listener.h @@ -73,6 +73,7 @@ class ProfilerListener : public CodeEventListener { const char* GetFunctionName(const char* name) { return function_and_resource_names_.GetFunctionName(name); } + size_t entries_count_for_test() const { return code_entries_.size(); } private: void RecordInliningInfo(CodeEntry* entry, AbstractCode* abstract_code); @@ -86,7 +87,7 @@ class ProfilerListener : public CodeEventListener { } StringsStorage function_and_resource_names_; - std::vector code_entries_; + std::vector> code_entries_; std::vector observers_; base::Mutex mutex_; diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc index 0659d8ec42..acb928a01c 100644 --- a/test/cctest/test-cpu-profiler.cc +++ b/test/cctest/test-cpu-profiler.cc @@ -2267,6 +2267,34 @@ TEST(StaticCollectSampleAPI) { profile->Delete(); } +TEST(CodeEntriesMemoryLeak) { + v8::HandleScope scope(CcTest::isolate()); + v8::Local env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Context::Scope context_scope(env); + + std::string source = "function start() {}\n"; + for (int i = 0; i < 1000; ++i) { + source += "function foo" + std::to_string(i) + "() { return " + + std::to_string(i) + + "; }\n" + "foo" + + std::to_string(i) + "();\n"; + } + CompileRun(source.c_str()); + v8::Local function = GetFunction(env, "start"); + + ProfilerHelper helper(env); + + for (int j = 0; j < 100; ++j) { + v8::CpuProfile* profile = helper.Run(function, nullptr, 0); + profile->Delete(); + } + ProfilerListener* profiler_listener = + CcTest::i_isolate()->logger()->profiler_listener(); + + CHECK_GE(10000ul, profiler_listener->entries_count_for_test()); +} + } // namespace test_cpu_profiler } // namespace internal } // namespace v8