diff --git a/lldb/include/lldb/Target/PathMappingList.h b/lldb/include/lldb/Target/PathMappingList.h --- a/lldb/include/lldb/Target/PathMappingList.h +++ b/lldb/include/lldb/Target/PathMappingList.h @@ -37,7 +37,9 @@ void Append(const PathMappingList &rhs, bool notify); - void AppendUnique(llvm::StringRef path, llvm::StringRef replacement, + /// Append pair without duplication. + /// \return whether appending suceeds without duplication or not. + bool AppendUnique(llvm::StringRef path, llvm::StringRef replacement, bool notify); void Clear(bool notify); diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h --- a/lldb/include/lldb/Target/Statistics.h +++ b/lldb/include/lldb/Target/Statistics.h @@ -133,6 +133,7 @@ void SetLaunchOrAttachTime(); void SetFirstPrivateStopTime(); void SetFirstPublicStopTime(); + void IncreaseSourceMapDeduceCount(); StatsDuration &GetCreateTime() { return m_create_time; } StatsSuccessFail &GetExpressionStats() { return m_expr_eval; } @@ -146,6 +147,7 @@ StatsSuccessFail m_expr_eval{"expressionEvaluation"}; StatsSuccessFail m_frame_var{"frameVariable"}; std::vector m_module_identifiers; + uint32_t m_source_map_deduce_count = 0; void CollectStats(Target &target); }; diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp --- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -261,8 +261,10 @@ if (!new_mapping_from.empty() && !new_mapping_to.empty()) { LLDB_LOG(log, "generating auto source map from {0} to {1}", new_mapping_from, new_mapping_to); - target.GetSourcePathMap().AppendUnique(new_mapping_from, new_mapping_to, - /*notify*/ true); + if (target.GetSourcePathMap().AppendUnique(new_mapping_from, + new_mapping_to, + /*notify*/ true)) + target.GetStatistics().IncreaseSourceMapDeduceCount(); } } } diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp --- a/lldb/source/Target/PathMappingList.cpp +++ b/lldb/source/Target/PathMappingList.cpp @@ -76,16 +76,17 @@ } } -void PathMappingList::AppendUnique(llvm::StringRef path, +bool PathMappingList::AppendUnique(llvm::StringRef path, llvm::StringRef replacement, bool notify) { auto normalized_path = NormalizePath(path); auto normalized_replacement = NormalizePath(replacement); for (const auto &pair : m_pairs) { if (pair.first.GetStringRef().equals(normalized_path) && pair.second.GetStringRef().equals(normalized_replacement)) - return; + return false; } Append(path, replacement, notify); + return true; } void PathMappingList::Insert(llvm::StringRef path, llvm::StringRef replacement, diff --git a/lldb/source/Target/Statistics.cpp b/lldb/source/Target/Statistics.cpp --- a/lldb/source/Target/Statistics.cpp +++ b/lldb/source/Target/Statistics.cpp @@ -136,6 +136,7 @@ target_metrics_json.try_emplace("breakpoints", std::move(breakpoints_array)); target_metrics_json.try_emplace("totalBreakpointResolveTime", totalBreakpointResolveTime); + target_metrics_json.try_emplace("sourceMapDeduceCount", m_source_map_deduce_count); return target_metrics_json; } @@ -161,6 +162,10 @@ m_first_public_stop_time = StatsClock::now(); } +void TargetStats::IncreaseSourceMapDeduceCount() { + ++m_source_map_deduce_count; +} + bool DebuggerStats::g_collecting_stats = false; llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger, diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py --- a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py @@ -445,6 +445,18 @@ self.assertEquals(entry[1], replacement, "source map entry 'replacement' does not match") + def verify_source_map_deduce_statistics(self, target, expected_count): + stream = lldb.SBStream() + res = target.GetStatistics().GetAsJSON(stream) + self.assertTrue(res.Success()) + debug_stats = json.loads(stream.GetData()) + self.assertEqual('targets' in debug_stats, True, + 'Make sure the "targets" key in in target.GetStatistics()') + target_stats = debug_stats['targets'][0] + self.assertNotEqual(target_stats, None) + self.assertEqual(target_stats['sourceMapDeduceCount'], expected_count) + + @skipIf(oslist=["windows"]) @no_debug_info_test def test_breakpoints_auto_source_map_relative(self): @@ -471,6 +483,7 @@ source_map_json = self.get_source_map_json() self.assertEquals(len(source_map_json), 0, "source map should be empty initially") + self.verify_source_map_deduce_statistics(target, 0) # Verify auto deduced source map when file path in debug info # is a suffix of request breakpoint file path @@ -483,6 +496,7 @@ source_map_json = self.get_source_map_json() self.assertEquals(len(source_map_json), 1, "source map should not be empty") self.verify_source_map_entry_pair(source_map_json[0], ".", "/x/y") + self.verify_source_map_deduce_statistics(target, 1) # Reset source map. self.runCmd("settings clear target.source-map")