[Lldb-commits] [lldb] [lldb-dap] Refactoring breakpoints to not use the `g_dap` reference. (PR #115208)

John Harrison via lldb-commits lldb-commits at lists.llvm.org
Wed Nov 6 16:39:00 PST 2024


https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/115208

>From 125c8976906ff25da6e212dff21d1b129575bd28 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Wed, 6 Nov 2024 09:36:48 -0800
Subject: [PATCH 1/2] [lldb-dap] Refactoring breakpoints to not use the `g_dap`
 reference.

Instead, when a breakpoint is constructed it will be passed a DAP reference that it should use for its lifetime.

This is part of a larger refactor to remove the global `g_dap` variable in favor of managing instances.
---
 lldb/tools/lldb-dap/Breakpoint.cpp            |   8 +-
 lldb/tools/lldb-dap/Breakpoint.h              |   9 +-
 lldb/tools/lldb-dap/BreakpointBase.cpp        |   4 +-
 lldb/tools/lldb-dap/BreakpointBase.h          |  12 +-
 lldb/tools/lldb-dap/DAP.cpp                   |  22 +-
 lldb/tools/lldb-dap/DAPForward.h              |   1 +
 lldb/tools/lldb-dap/ExceptionBreakpoint.cpp   |   6 +-
 lldb/tools/lldb-dap/ExceptionBreakpoint.h     |  12 +-
 lldb/tools/lldb-dap/FunctionBreakpoint.cpp    |   7 +-
 lldb/tools/lldb-dap/FunctionBreakpoint.h      |   4 +-
 lldb/tools/lldb-dap/InstructionBreakpoint.cpp |  13 +-
 lldb/tools/lldb-dap/InstructionBreakpoint.h   |  14 +-
 lldb/tools/lldb-dap/JSONUtils.cpp             |  64 ---
 lldb/tools/lldb-dap/JSONUtils.h               |  11 -
 lldb/tools/lldb-dap/SourceBreakpoint.cpp      |  17 +-
 lldb/tools/lldb-dap/SourceBreakpoint.h        |   3 +-
 lldb/tools/lldb-dap/Watchpoint.cpp            |   9 +-
 lldb/tools/lldb-dap/Watchpoint.h              |   8 +-
 lldb/tools/lldb-dap/lldb-dap.cpp              | 495 ++++++++----------
 19 files changed, 318 insertions(+), 401 deletions(-)

diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp
index 9ea7a42ca85a1e..aee2f87e2cc23e 100644
--- a/lldb/tools/lldb-dap/Breakpoint.cpp
+++ b/lldb/tools/lldb-dap/Breakpoint.cpp
@@ -7,11 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "Breakpoint.h"
-#include "DAP.h"
-#include "JSONUtils.h"
+
 #include "lldb/API/SBBreakpointLocation.h"
 #include "llvm/ADT/StringExtras.h"
 
+#include "DAP.h"
+#include "JSONUtils.h"
+
 using namespace lldb_dap;
 
 void Breakpoint::SetCondition() { bp.SetCondition(condition.c_str()); }
@@ -51,7 +53,7 @@ void Breakpoint::CreateJsonObject(llvm::json::Object &object) {
 
   if (bp_addr.IsValid()) {
     std::string formatted_addr =
-        "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(g_dap.target));
+        "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(bp.GetTarget()));
     object.try_emplace("instructionReference", formatted_addr);
     auto line_entry = bp_addr.GetLineEntry();
     const auto line = line_entry.GetLine();
diff --git a/lldb/tools/lldb-dap/Breakpoint.h b/lldb/tools/lldb-dap/Breakpoint.h
index ee9d3736d6190f..cffeb2fab1f0ef 100644
--- a/lldb/tools/lldb-dap/Breakpoint.h
+++ b/lldb/tools/lldb-dap/Breakpoint.h
@@ -9,18 +9,19 @@
 #ifndef LLDB_TOOLS_LLDB_DAP_BREAKPOINT_H
 #define LLDB_TOOLS_LLDB_DAP_BREAKPOINT_H
 
-#include "BreakpointBase.h"
 #include "lldb/API/SBBreakpoint.h"
 
+#include "BreakpointBase.h"
+
 namespace lldb_dap {
 
 struct Breakpoint : public BreakpointBase {
   // The LLDB breakpoint associated wit this source breakpoint
   lldb::SBBreakpoint bp;
 
-  Breakpoint() = default;
-  Breakpoint(const llvm::json::Object &obj) : BreakpointBase(obj){};
-  Breakpoint(lldb::SBBreakpoint bp) : bp(bp) {}
+  Breakpoint(DAP &d) : BreakpointBase(d) {}
+  Breakpoint(DAP &d, const llvm::json::Object &obj) : BreakpointBase(d, obj) {}
+  Breakpoint(DAP &d, lldb::SBBreakpoint bp) : BreakpointBase(d), bp(bp) {}
 
   void SetCondition() override;
   void SetHitCondition() override;
diff --git a/lldb/tools/lldb-dap/BreakpointBase.cpp b/lldb/tools/lldb-dap/BreakpointBase.cpp
index f3cb06a3562d48..c5d7a9778df018 100644
--- a/lldb/tools/lldb-dap/BreakpointBase.cpp
+++ b/lldb/tools/lldb-dap/BreakpointBase.cpp
@@ -11,8 +11,8 @@
 
 using namespace lldb_dap;
 
-BreakpointBase::BreakpointBase(const llvm::json::Object &obj)
-    : condition(std::string(GetString(obj, "condition"))),
+BreakpointBase::BreakpointBase(DAP &d, const llvm::json::Object &obj)
+    : dap(d), condition(std::string(GetString(obj, "condition"))),
       hitCondition(std::string(GetString(obj, "hitCondition"))) {}
 
 void BreakpointBase::UpdateBreakpoint(const BreakpointBase &request_bp) {
diff --git a/lldb/tools/lldb-dap/BreakpointBase.h b/lldb/tools/lldb-dap/BreakpointBase.h
index 79301480e0e588..bb660ddc451bd5 100644
--- a/lldb/tools/lldb-dap/BreakpointBase.h
+++ b/lldb/tools/lldb-dap/BreakpointBase.h
@@ -9,12 +9,17 @@
 #ifndef LLDB_TOOLS_LLDB_DAP_BREAKPOINTBASE_H
 #define LLDB_TOOLS_LLDB_DAP_BREAKPOINTBASE_H
 
-#include "llvm/Support/JSON.h"
 #include <string>
 
+#include "llvm/Support/JSON.h"
+
+#include "DAPForward.h"
+
 namespace lldb_dap {
 
 struct BreakpointBase {
+  // Associated DAP session.
+  DAP &dap;
 
   // An optional expression for conditional breakpoints.
   std::string condition;
@@ -22,8 +27,9 @@ struct BreakpointBase {
   // ignored. The backend is expected to interpret the expression as needed
   std::string hitCondition;
 
-  BreakpointBase() = default;
-  BreakpointBase(const llvm::json::Object &obj);
+  BreakpointBase(DAP &d) : dap(d) {}
+  BreakpointBase(DAP &d, const llvm::json::Object &obj);
+  BreakpointBase(const BreakpointBase &) = default;
   virtual ~BreakpointBase() = default;
 
   virtual void SetCondition() = 0;
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 283392270ba26c..647e28080b6339 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -74,21 +74,21 @@ void DAP::PopulateExceptionBreakpoints() {
     exception_breakpoints = std::vector<ExceptionBreakpoint>{};
 
     if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeC_plus_plus)) {
-      exception_breakpoints->emplace_back("cpp_catch", "C++ Catch",
+      exception_breakpoints->emplace_back(*this, "cpp_catch", "C++ Catch",
                                           lldb::eLanguageTypeC_plus_plus);
-      exception_breakpoints->emplace_back("cpp_throw", "C++ Throw",
+      exception_breakpoints->emplace_back(*this, "cpp_throw", "C++ Throw",
                                           lldb::eLanguageTypeC_plus_plus);
     }
     if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeObjC)) {
-      exception_breakpoints->emplace_back("objc_catch", "Objective-C Catch",
-                                          lldb::eLanguageTypeObjC);
-      exception_breakpoints->emplace_back("objc_throw", "Objective-C Throw",
-                                          lldb::eLanguageTypeObjC);
+      exception_breakpoints->emplace_back(
+          *this, "objc_catch", "Objective-C Catch", lldb::eLanguageTypeObjC);
+      exception_breakpoints->emplace_back(
+          *this, "objc_throw", "Objective-C Throw", lldb::eLanguageTypeObjC);
     }
     if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeSwift)) {
-      exception_breakpoints->emplace_back("swift_catch", "Swift Catch",
+      exception_breakpoints->emplace_back(*this, "swift_catch", "Swift Catch",
                                           lldb::eLanguageTypeSwift);
-      exception_breakpoints->emplace_back("swift_throw", "Swift Throw",
+      exception_breakpoints->emplace_back(*this, "swift_throw", "Swift Throw",
                                           lldb::eLanguageTypeSwift);
     }
     // Besides handling the hardcoded list of languages from above, we try to
@@ -119,7 +119,7 @@ void DAP::PopulateExceptionBreakpoints() {
             raw_throw_keyword ? raw_throw_keyword : "throw";
 
         exception_breakpoints->emplace_back(
-            raw_lang_name + "_" + throw_keyword,
+            *this, raw_lang_name + "_" + throw_keyword,
             capitalized_lang_name + " " + capitalize(throw_keyword), lang);
       }
 
@@ -130,7 +130,7 @@ void DAP::PopulateExceptionBreakpoints() {
             raw_catch_keyword ? raw_catch_keyword : "catch";
 
         exception_breakpoints->emplace_back(
-            raw_lang_name + "_" + catch_keyword,
+            *this, raw_lang_name + "_" + catch_keyword,
             capitalized_lang_name + " " + capitalize(catch_keyword), lang);
       }
     }
@@ -1060,7 +1060,7 @@ void DAP::SetThreadFormat(llvm::StringRef format) {
 InstructionBreakpoint *
 DAP::GetInstructionBreakpoint(const lldb::break_id_t bp_id) {
   for (auto &bp : instruction_breakpoints) {
-    if (bp.second.id == bp_id)
+    if (bp.second.bp.GetID() == bp_id)
       return &bp.second;
   }
   return nullptr;
diff --git a/lldb/tools/lldb-dap/DAPForward.h b/lldb/tools/lldb-dap/DAPForward.h
index 159d999a63c820..2bb54d806fd6fb 100644
--- a/lldb/tools/lldb-dap/DAPForward.h
+++ b/lldb/tools/lldb-dap/DAPForward.h
@@ -16,6 +16,7 @@ struct FunctionBreakpoint;
 struct SourceBreakpoint;
 struct Watchpoint;
 struct InstructionBreakpoint;
+struct DAP;
 } // namespace lldb_dap
 
 namespace lldb {
diff --git a/lldb/tools/lldb-dap/ExceptionBreakpoint.cpp b/lldb/tools/lldb-dap/ExceptionBreakpoint.cpp
index 130c237e65441d..e9bb11face49df 100644
--- a/lldb/tools/lldb-dap/ExceptionBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/ExceptionBreakpoint.cpp
@@ -17,8 +17,8 @@ void ExceptionBreakpoint::SetBreakpoint() {
     return;
   bool catch_value = filter.find("_catch") != std::string::npos;
   bool throw_value = filter.find("_throw") != std::string::npos;
-  bp = g_dap.target.BreakpointCreateForException(language, catch_value,
-                                                 throw_value);
+  bp = dap.target.BreakpointCreateForException(language, catch_value,
+                                               throw_value);
   // See comments in BreakpointBase::GetBreakpointLabel() for details of why
   // we add a label to our breakpoints.
   bp.AddName(BreakpointBase::GetBreakpointLabel());
@@ -27,7 +27,7 @@ void ExceptionBreakpoint::SetBreakpoint() {
 void ExceptionBreakpoint::ClearBreakpoint() {
   if (!bp.IsValid())
     return;
-  g_dap.target.BreakpointDelete(bp.GetID());
+  dap.target.BreakpointDelete(bp.GetID());
   bp = lldb::SBBreakpoint();
 }
 
diff --git a/lldb/tools/lldb-dap/ExceptionBreakpoint.h b/lldb/tools/lldb-dap/ExceptionBreakpoint.h
index 7b81d845cb26be..7819bea726a1d0 100644
--- a/lldb/tools/lldb-dap/ExceptionBreakpoint.h
+++ b/lldb/tools/lldb-dap/ExceptionBreakpoint.h
@@ -13,17 +13,21 @@
 
 #include "lldb/API/SBBreakpoint.h"
 
+#include "DAPForward.h"
+
 namespace lldb_dap {
 
 struct ExceptionBreakpoint {
+  DAP &dap;
   std::string filter;
   std::string label;
   lldb::LanguageType language;
-  bool default_value;
+  bool default_value = false;
   lldb::SBBreakpoint bp;
-  ExceptionBreakpoint(std::string f, std::string l, lldb::LanguageType lang)
-      : filter(std::move(f)), label(std::move(l)), language(lang),
-        default_value(false), bp() {}
+  ExceptionBreakpoint(DAP &d, std::string f, std::string l,
+                      lldb::LanguageType lang)
+      : dap(d), filter(std::move(f)), label(std::move(l)), language(lang),
+        bp() {}
 
   void SetBreakpoint();
   void ClearBreakpoint();
diff --git a/lldb/tools/lldb-dap/FunctionBreakpoint.cpp b/lldb/tools/lldb-dap/FunctionBreakpoint.cpp
index 216c685f633da8..ef6df6c0dc91cc 100644
--- a/lldb/tools/lldb-dap/FunctionBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/FunctionBreakpoint.cpp
@@ -7,18 +7,19 @@
 //===----------------------------------------------------------------------===//
 
 #include "FunctionBreakpoint.h"
+
 #include "DAP.h"
 #include "JSONUtils.h"
 
 namespace lldb_dap {
 
-FunctionBreakpoint::FunctionBreakpoint(const llvm::json::Object &obj)
-    : Breakpoint(obj), functionName(std::string(GetString(obj, "name"))) {}
+FunctionBreakpoint::FunctionBreakpoint(DAP &d, const llvm::json::Object &obj)
+    : Breakpoint(d, obj), functionName(std::string(GetString(obj, "name"))) {}
 
 void FunctionBreakpoint::SetBreakpoint() {
   if (functionName.empty())
     return;
-  bp = g_dap.target.BreakpointCreateByName(functionName.c_str());
+  bp = dap.target.BreakpointCreateByName(functionName.c_str());
   Breakpoint::SetBreakpoint();
 }
 
diff --git a/lldb/tools/lldb-dap/FunctionBreakpoint.h b/lldb/tools/lldb-dap/FunctionBreakpoint.h
index b15ff1931a6b22..93f0b93b35291d 100644
--- a/lldb/tools/lldb-dap/FunctionBreakpoint.h
+++ b/lldb/tools/lldb-dap/FunctionBreakpoint.h
@@ -10,14 +10,14 @@
 #define LLDB_TOOLS_LLDB_DAP_FUNCTIONBREAKPOINT_H
 
 #include "Breakpoint.h"
+#include "DAPForward.h"
 
 namespace lldb_dap {
 
 struct FunctionBreakpoint : public Breakpoint {
   std::string functionName;
 
-  FunctionBreakpoint() = default;
-  FunctionBreakpoint(const llvm::json::Object &obj);
+  FunctionBreakpoint(DAP &dap, const llvm::json::Object &obj);
 
   // Set this breakpoint in LLDB as a new breakpoint
   void SetBreakpoint();
diff --git a/lldb/tools/lldb-dap/InstructionBreakpoint.cpp b/lldb/tools/lldb-dap/InstructionBreakpoint.cpp
index e3a8460bb7b301..8c5c32c9270b41 100644
--- a/lldb/tools/lldb-dap/InstructionBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/InstructionBreakpoint.cpp
@@ -8,22 +8,25 @@
 //===----------------------------------------------------------------------===//
 
 #include "InstructionBreakpoint.h"
+
 #include "DAP.h"
 #include "JSONUtils.h"
 
 namespace lldb_dap {
 
 // Instruction Breakpoint
-InstructionBreakpoint::InstructionBreakpoint(const llvm::json::Object &obj)
-    : Breakpoint(obj), instructionAddressReference(LLDB_INVALID_ADDRESS), id(0),
+InstructionBreakpoint::InstructionBreakpoint(DAP &d,
+                                             const llvm::json::Object &obj)
+    : Breakpoint(d, obj), instructionAddressReference(LLDB_INVALID_ADDRESS),
       offset(GetSigned(obj, "offset", 0)) {
   GetString(obj, "instructionReference")
       .getAsInteger(0, instructionAddressReference);
   instructionAddressReference += offset;
 }
 
-void InstructionBreakpoint::SetInstructionBreakpoint() {
-  bp = g_dap.target.BreakpointCreateByAddress(instructionAddressReference);
-  id = bp.GetID();
+void InstructionBreakpoint::SetBreakpoint() {
+  bp = dap.target.BreakpointCreateByAddress(instructionAddressReference);
+  Breakpoint::SetBreakpoint();
 }
+
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/InstructionBreakpoint.h b/lldb/tools/lldb-dap/InstructionBreakpoint.h
index 53912af46ca148..cc251c96f5bdd8 100644
--- a/lldb/tools/lldb-dap/InstructionBreakpoint.h
+++ b/lldb/tools/lldb-dap/InstructionBreakpoint.h
@@ -10,7 +10,12 @@
 #ifndef LLDB_TOOLS_LLDB_DAP_INSTRUCTIONBREAKPOINT_H
 #define LLDB_TOOLS_LLDB_DAP_INSTRUCTIONBREAKPOINT_H
 
+#include <cstdint>
+
+#include "lldb/lldb-types.h"
+
 #include "Breakpoint.h"
+#include "DAPForward.h"
 
 namespace lldb_dap {
 
@@ -18,16 +23,15 @@ namespace lldb_dap {
 struct InstructionBreakpoint : public Breakpoint {
 
   lldb::addr_t instructionAddressReference;
-  int32_t id;
   int32_t offset;
 
-  InstructionBreakpoint()
-      : Breakpoint(), instructionAddressReference(LLDB_INVALID_ADDRESS), id(0),
+  InstructionBreakpoint(DAP &d)
+      : Breakpoint(d), instructionAddressReference(LLDB_INVALID_ADDRESS),
         offset(0) {}
-  InstructionBreakpoint(const llvm::json::Object &obj);
+  InstructionBreakpoint(DAP &d, const llvm::json::Object &obj);
 
   // Set instruction breakpoint in LLDB as a new breakpoint
-  void SetInstructionBreakpoint();
+  void SetBreakpoint();
 };
 
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 97fe6b4f9f05db..70bebddc91119d 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -831,70 +831,6 @@ llvm::json::Value CreateExtendedStackFrameLabel(lldb::SBThread &thread) {
                                               {"presentationHint", "label"}});
 }
 
-// Response to `setInstructionBreakpoints` request.
-// "Breakpoint": {
-//   "type": "object",
-//   "description": "Response to `setInstructionBreakpoints` request.",
-//   "properties": {
-//     "id": {
-//       "type": "number",
-//       "description": "The identifier for the breakpoint. It is needed if
-//       breakpoint events are used to update or remove breakpoints."
-//     },
-//     "verified": {
-//       "type": "boolean",
-//       "description": "If true, the breakpoint could be set (but not
-//       necessarily at the desired location."
-//     },
-//     "message": {
-//       "type": "string",
-//       "description": "A message about the state of the breakpoint.
-//       This is shown to the user and can be used to explain why a breakpoint
-//       could not be verified."
-//     },
-//     "source": {
-//       "type": "Source",
-//       "description": "The source where the breakpoint is located."
-//     },
-//     "line": {
-//       "type": "number",
-//       "description": "The start line of the actual range covered by the
-//       breakpoint."
-//     },
-//     "column": {
-//       "type": "number",
-//       "description": "The start column of the actual range covered by the
-//       breakpoint."
-//     },
-//     "endLine": {
-//       "type": "number",
-//       "description": "The end line of the actual range covered by the
-//       breakpoint."
-//     },
-//     "endColumn": {
-//       "type": "number",
-//       "description": "The end column of the actual range covered by the
-//       breakpoint. If no end line is given, then the end column is assumed to
-//       be in the start line."
-//     },
-//     "instructionReference": {
-//       "type": "string",
-//       "description": "A memory reference to where the breakpoint is set."
-//     },
-//     "offset": {
-//       "type": "number",
-//       "description": "The offset from the instruction reference.
-//       This can be negative."
-//     },
-//   },
-//   "required": [ "id", "verified", "line"]
-// }
-llvm::json::Value CreateInstructionBreakpoint(BreakpointBase *ibp) {
-  llvm::json::Object object;
-  ibp->CreateJsonObject(object);
-  return llvm::json::Value(std::move(object));
-}
-
 // "Thread": {
 //   "type": "object",
 //   "description": "A Thread",
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index 54fc4323475723..43056f3dc14566 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -380,17 +380,6 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame);
 ///     definition outlined by Microsoft.
 llvm::json::Value CreateExtendedStackFrameLabel(lldb::SBThread &thread);
 
-/// Create a "instruction" object for a LLDB disassemble object as described in
-/// the Visual Studio Code debug adaptor definition.
-///
-/// \param[in] bp
-///     The LLDB instruction object used to populate the disassembly
-///     instruction.
-/// \return
-///     A "Scope" JSON object with that follows the formal JSON
-///     definition outlined by Microsoft.
-llvm::json::Value CreateInstructionBreakpoint(BreakpointBase *ibp);
-
 /// Create a "Thread" object for a LLDB thread object.
 ///
 /// This function will fill in the following keys in the returned
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
index d1a3a5bedb0ae2..7415a0914dad43 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
@@ -12,15 +12,16 @@
 
 namespace lldb_dap {
 
-SourceBreakpoint::SourceBreakpoint(const llvm::json::Object &obj)
-    : Breakpoint(obj), logMessage(std::string(GetString(obj, "logMessage"))),
+SourceBreakpoint::SourceBreakpoint(DAP &dap, const llvm::json::Object &obj)
+    : Breakpoint(dap, obj),
+      logMessage(std::string(GetString(obj, "logMessage"))),
       line(GetUnsigned(obj, "line", 0)), column(GetUnsigned(obj, "column", 0)) {
 }
 
 void SourceBreakpoint::SetBreakpoint(const llvm::StringRef source_path) {
   lldb::SBFileSpecList module_list;
-  bp = g_dap.target.BreakpointCreateByLocation(source_path.str().c_str(), line,
-                                               column, 0, module_list);
+  bp = dap.target.BreakpointCreateByLocation(source_path.str().c_str(), line,
+                                             column, 0, module_list);
   if (!logMessage.empty())
     SetLogMessage();
   Breakpoint::SetBreakpoint();
@@ -279,7 +280,7 @@ void SourceBreakpoint::SetLogMessage() {
 void SourceBreakpoint::NotifyLogMessageError(llvm::StringRef error) {
   std::string message = "Log message has error: ";
   message += error;
-  g_dap.SendOutput(OutputType::Console, message);
+  dap.SendOutput(OutputType::Console, message);
 }
 
 /*static*/
@@ -304,14 +305,16 @@ bool SourceBreakpoint::BreakpointHitCallback(
           frame.GetValueForVariablePath(expr, lldb::eDynamicDontRunTarget);
       if (value.GetError().Fail())
         value = frame.EvaluateExpression(expr);
-      output += VariableDescription(value).display_value;
+      output +=
+          VariableDescription(value, bp->dap.enable_auto_variable_summaries)
+              .display_value;
     } else {
       output += messagePart.text;
     }
   }
   if (!output.empty() && output.back() != '\n')
     output.push_back('\n'); // Ensure log message has line break.
-  g_dap.SendOutput(OutputType::Console, output.c_str());
+  bp->dap.SendOutput(OutputType::Console, output.c_str());
 
   // Do not stop.
   return false;
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.h b/lldb/tools/lldb-dap/SourceBreakpoint.h
index aa3fbe6d0f96d2..113c0efbddcc5c 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.h
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.h
@@ -31,8 +31,7 @@ struct SourceBreakpoint : public Breakpoint {
   uint32_t line;   ///< The source line of the breakpoint or logpoint
   uint32_t column; ///< An optional source column of the breakpoint
 
-  SourceBreakpoint() : Breakpoint(), line(0), column(0) {}
-  SourceBreakpoint(const llvm::json::Object &obj);
+  SourceBreakpoint(DAP &d, const llvm::json::Object &obj);
 
   // Set this breakpoint in LLDB as a new breakpoint
   void SetBreakpoint(const llvm::StringRef source_path);
diff --git a/lldb/tools/lldb-dap/Watchpoint.cpp b/lldb/tools/lldb-dap/Watchpoint.cpp
index 21765509449140..56dd5434269151 100644
--- a/lldb/tools/lldb-dap/Watchpoint.cpp
+++ b/lldb/tools/lldb-dap/Watchpoint.cpp
@@ -7,12 +7,15 @@
 //===----------------------------------------------------------------------===//
 
 #include "Watchpoint.h"
+
+#include "llvm/ADT/StringExtras.h"
+
 #include "DAP.h"
 #include "JSONUtils.h"
-#include "llvm/ADT/StringExtras.h"
 
 namespace lldb_dap {
-Watchpoint::Watchpoint(const llvm::json::Object &obj) : BreakpointBase(obj) {
+Watchpoint::Watchpoint(DAP &d, const llvm::json::Object &obj)
+    : BreakpointBase(d, obj) {
   llvm::StringRef dataId = GetString(obj, "dataId");
   std::string accessType = GetString(obj, "accessType").str();
   auto [addr_str, size_str] = dataId.split('/');
@@ -42,7 +45,7 @@ void Watchpoint::CreateJsonObject(llvm::json::Object &object) {
 }
 
 void Watchpoint::SetWatchpoint() {
-  wp = g_dap.target.WatchpointCreateByAddress(addr, size, options, error);
+  wp = dap.target.WatchpointCreateByAddress(addr, size, options, error);
   if (!condition.empty())
     SetCondition();
   if (!hitCondition.empty())
diff --git a/lldb/tools/lldb-dap/Watchpoint.h b/lldb/tools/lldb-dap/Watchpoint.h
index 4d2e58ed753360..b84b4b1c9ff3d3 100644
--- a/lldb/tools/lldb-dap/Watchpoint.h
+++ b/lldb/tools/lldb-dap/Watchpoint.h
@@ -9,11 +9,12 @@
 #ifndef LLDB_TOOLS_LLDB_DAP_WATCHPOINT_H
 #define LLDB_TOOLS_LLDB_DAP_WATCHPOINT_H
 
-#include "BreakpointBase.h"
 #include "lldb/API/SBError.h"
 #include "lldb/API/SBWatchpoint.h"
 #include "lldb/API/SBWatchpointOptions.h"
 
+#include "BreakpointBase.h"
+
 namespace lldb_dap {
 
 struct Watchpoint : public BreakpointBase {
@@ -24,9 +25,8 @@ struct Watchpoint : public BreakpointBase {
   lldb::SBWatchpoint wp;
   lldb::SBError error;
 
-  Watchpoint() = default;
-  Watchpoint(const llvm::json::Object &obj);
-  Watchpoint(lldb::SBWatchpoint wp) : wp(wp) {}
+  Watchpoint(DAP &d, const llvm::json::Object &obj);
+  Watchpoint(DAP &d, lldb::SBWatchpoint wp) : BreakpointBase(d), wp(wp) {}
 
   void SetCondition() override;
   void SetHitCondition() override;
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index a2f7be2b214e4a..525cb2d5eddab5 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -6,17 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "DAP.h"
-#include "FifoFiles.h"
-#include "RunInTerminal.h"
-#include "Watchpoint.h"
-#include "lldb/API/SBDeclaration.h"
-#include "lldb/API/SBInstruction.h"
-#include "lldb/API/SBListener.h"
-#include "lldb/API/SBMemoryRegionInfo.h"
-#include "lldb/API/SBStringList.h"
-#include "llvm/Support/Base64.h"
-
 #include <cassert>
 #include <climits>
 #include <cstdarg>
@@ -54,16 +43,23 @@
 #include <thread>
 #include <vector>
 
+#include "lldb/API/SBDeclaration.h"
+#include "lldb/API/SBInstruction.h"
+#include "lldb/API/SBListener.h"
+#include "lldb/API/SBMemoryRegionInfo.h"
 #include "lldb/API/SBStream.h"
+#include "lldb/API/SBStringList.h"
 #include "lldb/Host/Config.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"
 #include "llvm/Option/Option.h"
+#include "llvm/Support/Base64.h"
 #include "llvm/Support/Errno.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/InitLLVM.h"
@@ -71,9 +67,13 @@
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/raw_ostream.h"
 
+#include "DAP.h"
+#include "FifoFiles.h"
 #include "JSONUtils.h"
 #include "LLDBUtils.h"
 #include "OutputRedirector.h"
+#include "RunInTerminal.h"
+#include "Watchpoint.h"
 
 #if defined(_WIN32)
 #ifndef PATH_MAX
@@ -526,8 +526,8 @@ void EventThreadFunction() {
         if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) {
           auto event_type =
               lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(event);
-          auto bp =
-              Breakpoint(lldb::SBBreakpoint::GetBreakpointFromEvent(event));
+          auto bp = Breakpoint(
+              g_dap, lldb::SBBreakpoint::GetBreakpointFromEvent(event));
           // If the breakpoint was originated from the IDE, it will have the
           // BreakpointBase::GetBreakpointLabel() label attached. Regardless
           // of wether the locations were added or removed, the breakpoint
@@ -2689,10 +2689,10 @@ void request_setBreakpoints(const llvm::json::Object &request) {
   llvm::json::Object response;
   lldb::SBError error;
   FillResponse(request, response);
-  auto arguments = request.getObject("arguments");
-  auto source = arguments->getObject("source");
+  const auto *arguments = request.getObject("arguments");
+  const auto *source = arguments->getObject("source");
   const auto path = GetString(source, "path");
-  auto breakpoints = arguments->getArray("breakpoints");
+  const auto *breakpoints = arguments->getArray("breakpoints");
   llvm::json::Array response_breakpoints;
 
   // Decode the source breakpoint infos for this "setBreakpoints" request
@@ -2701,28 +2701,21 @@ void request_setBreakpoints(const llvm::json::Object &request) {
   // to an empty array.
   if (breakpoints) {
     for (const auto &bp : *breakpoints) {
-      auto bp_obj = bp.getAsObject();
+      const auto *bp_obj = bp.getAsObject();
       if (bp_obj) {
-        SourceBreakpoint src_bp(*bp_obj);
-        request_bps[src_bp.line] = src_bp;
-
+        SourceBreakpoint src_bp(g_dap, *bp_obj);
+        request_bps.try_emplace(src_bp.line, src_bp);
+        const auto [kv, inserted] =
+            g_dap.source_breakpoints[path].try_emplace(src_bp.line, src_bp);
         // We check if this breakpoint already exists to update it
-        auto existing_source_bps = g_dap.source_breakpoints.find(path);
-        if (existing_source_bps != g_dap.source_breakpoints.end()) {
-          const auto &existing_bp =
-              existing_source_bps->second.find(src_bp.line);
-          if (existing_bp != existing_source_bps->second.end()) {
-            existing_bp->second.UpdateBreakpoint(src_bp);
-            AppendBreakpoint(&existing_bp->second, response_breakpoints, path,
-                             src_bp.line);
-            continue;
-          }
+        if (inserted) {
+          kv->getSecond().SetBreakpoint(path.data());
+        } else {
+          kv->getSecond().UpdateBreakpoint(src_bp);
         }
-        // At this point the breakpoint is new
-        g_dap.source_breakpoints[path][src_bp.line] = src_bp;
-        SourceBreakpoint &new_bp = g_dap.source_breakpoints[path][src_bp.line];
-        new_bp.SetBreakpoint(path.data());
-        AppendBreakpoint(&new_bp, response_breakpoints, path, new_bp.line);
+
+        AppendBreakpoint(&kv->getSecond(), response_breakpoints, path,
+                         src_bp.line);
       }
     }
   }
@@ -2799,8 +2792,8 @@ void request_setExceptionBreakpoints(const llvm::json::Object &request) {
   llvm::json::Object response;
   lldb::SBError error;
   FillResponse(request, response);
-  auto arguments = request.getObject("arguments");
-  auto filters = arguments->getArray("filters");
+  const auto *arguments = request.getObject("arguments");
+  const auto *filters = arguments->getArray("filters");
   // Keep a list of any exception breakpoint filter names that weren't set
   // so we can clear any exception breakpoints if needed.
   std::set<std::string> unset_filters;
@@ -2905,51 +2898,39 @@ void request_setFunctionBreakpoints(const llvm::json::Object &request) {
   llvm::json::Object response;
   lldb::SBError error;
   FillResponse(request, response);
-  auto arguments = request.getObject("arguments");
-  auto breakpoints = arguments->getArray("breakpoints");
-  FunctionBreakpointMap request_bps;
+  const auto *arguments = request.getObject("arguments");
+  const auto *breakpoints = arguments->getArray("breakpoints");
   llvm::json::Array response_breakpoints;
-  for (const auto &value : *breakpoints) {
-    auto bp_obj = value.getAsObject();
-    if (bp_obj == nullptr)
-      continue;
-    FunctionBreakpoint func_bp(*bp_obj);
-    request_bps[func_bp.functionName] = std::move(func_bp);
-  }
 
-  std::vector<llvm::StringRef> remove_names;
-  // Disable any function breakpoints that aren't in the request_bps.
+  // Disable any function breakpoints that aren't in this request.
   // There is no call to remove function breakpoints other than calling this
   // function with a smaller or empty "breakpoints" list.
-  for (auto &pair : g_dap.function_breakpoints) {
-    auto request_pos = request_bps.find(pair.first());
-    if (request_pos == request_bps.end()) {
-      // This function breakpoint no longer exists delete it from LLDB
-      g_dap.target.BreakpointDelete(pair.second.bp.GetID());
-      remove_names.push_back(pair.first());
+  const auto name_iter = g_dap.function_breakpoints.keys();
+  llvm::SetVector<llvm::StringRef> seen(name_iter.begin(), name_iter.end());
+  for (const auto &value : *breakpoints) {
+    const auto *bp_obj = value.getAsObject();
+    if (!bp_obj)
+      continue;
+    FunctionBreakpoint fn_bp(g_dap, *bp_obj);
+    const auto [kv, inserted] = g_dap.function_breakpoints.try_emplace(
+        fn_bp.functionName, g_dap, *bp_obj);
+    if (inserted) {
+      kv->second.SetBreakpoint();
     } else {
-      // Update the existing breakpoint as any setting withing the function
-      // breakpoint might have changed.
-      pair.second.UpdateBreakpoint(request_pos->second);
-      // Remove this breakpoint from the request breakpoints since we have
-      // handled it here and we don't need to set a new breakpoint below.
-      request_bps.erase(request_pos);
-      // Add this breakpoint info to the response
-      AppendBreakpoint(&pair.second, response_breakpoints);
+      kv->second.UpdateBreakpoint(fn_bp);
     }
+
+    AppendBreakpoint(&kv->second, response_breakpoints);
+    seen.remove(fn_bp.functionName);
   }
+
   // Remove any breakpoints that are no longer in our list
-  for (const auto &name : remove_names)
+  for (const auto &name : seen) {
+    auto fn_bp = g_dap.function_breakpoints.find(name);
+    if (fn_bp == g_dap.function_breakpoints.end())
+      continue;
+    g_dap.target.BreakpointDelete(fn_bp->second.bp.GetID());
     g_dap.function_breakpoints.erase(name);
-
-  // Any breakpoints that are left in "request_bps" are breakpoints that
-  // need to be set.
-  for (auto &pair : request_bps) {
-    // Add this breakpoint info to the response
-    g_dap.function_breakpoints[pair.first()] = std::move(pair.second);
-    FunctionBreakpoint &new_bp = g_dap.function_breakpoints[pair.first()];
-    new_bp.SetBreakpoint();
-    AppendBreakpoint(&new_bp, response_breakpoints);
   }
 
   llvm::json::Object body;
@@ -3202,8 +3183,7 @@ void request_setDataBreakpoints(const llvm::json::Object &request) {
     for (const auto &bp : *breakpoints) {
       const auto *bp_obj = bp.getAsObject();
       if (bp_obj) {
-        Watchpoint wp(*bp_obj);
-        watchpoints.push_back(wp);
+        watchpoints.emplace_back(g_dap, *bp_obj);
       }
     }
   }
@@ -4551,7 +4531,7 @@ void request__testGetTargetBreakpoints(const llvm::json::Object &request) {
   FillResponse(request, response);
   llvm::json::Array response_breakpoints;
   for (uint32_t i = 0; g_dap.target.GetBreakpointAtIndex(i).IsValid(); ++i) {
-    auto bp = Breakpoint(g_dap.target.GetBreakpointAtIndex(i));
+    auto bp = Breakpoint(g_dap, g_dap.target.GetBreakpointAtIndex(i));
     AppendBreakpoint(&bp, response_breakpoints);
   }
   llvm::json::Object body;
@@ -4560,10 +4540,11 @@ void request__testGetTargetBreakpoints(const llvm::json::Object &request) {
   g_dap.SendJSON(llvm::json::Value(std::move(response)));
 }
 
-// "SetInstructionBreakpointsRequest" : {
-//   "allOf" : [
-//     {"$ref" : "#/definitions/Request"}, {
-//       "type" : "object",
+// "SetInstructionBreakpointsRequest": {
+//   "allOf": [
+//     {"$ref": "#/definitions/Request"},
+//     {
+//       "type": "object",
 //       "description" :
 //           "Replaces all existing instruction breakpoints. Typically, "
 //           "instruction breakpoints would be set from a disassembly window. "
@@ -4572,235 +4553,219 @@ void request__testGetTargetBreakpoints(const llvm::json::Object &request) {
 //           "(with reason `instruction breakpoint`) is generated.\nClients "
 //           "should only call this request if the corresponding capability "
 //           "`supportsInstructionBreakpoints` is true.",
-//       "properties" : {
-//         "command" : {"type" : "string", "enum" :
-//         ["setInstructionBreakpoints"]}, "arguments" :
-//             {"$ref" : "#/definitions/SetInstructionBreakpointsArguments"}
+//       "properties": {
+//         "command": { "type": "string", "enum": ["setInstructionBreakpoints"]
+//         }, "arguments": {"$ref":
+//         "#/definitions/SetInstructionBreakpointsArguments"}
 //       },
-//       "required" : [ "command", "arguments" ]
+//       "required": [ "command", "arguments" ]
 //     }
 //   ]
 // },
-//                                      "SetInstructionBreakpointsArguments"
-//     : {
-//       "type" : "object",
-//       "description" : "Arguments for `setInstructionBreakpoints` request",
-//       "properties" : {
-//         "breakpoints" : {
-//           "type" : "array",
-//           "items" : {"$ref" : "#/definitions/InstructionBreakpoint"},
-//           "description" : "The instruction references of the breakpoints"
-//         }
-//       },
-//       "required" : ["breakpoints"]
-//     },
-//       "SetInstructionBreakpointsResponse"
-//     : {
-//       "allOf" : [
-//         {"$ref" : "#/definitions/Response"}, {
-//           "type" : "object",
-//           "description" : "Response to `setInstructionBreakpoints` request",
-//           "properties" : {
-//             "body" : {
-//               "type" : "object",
-//               "properties" : {
-//                 "breakpoints" : {
-//                   "type" : "array",
-//                   "items" : {"$ref" : "#/definitions/Breakpoint"},
-//                   "description" :
-//                       "Information about the breakpoints. The array elements
-//                       " "correspond to the elements of the `breakpoints`
-//                       array."
-//                 }
-//               },
-//               "required" : ["breakpoints"]
+// "SetInstructionBreakpointsArguments": {
+//   "type": "object",
+//   "description": "Arguments for `setInstructionBreakpoints` request",
+//   "properties": {
+//     "breakpoints": {
+//       "type": "array",
+//       "items": {"$ref": "#/definitions/InstructionBreakpoint"},
+//       "description": "The instruction references of the breakpoints"
+//     }
+//   },
+//   "required": ["breakpoints"]
+// },
+// "SetInstructionBreakpointsResponse": {
+//   "allOf": [
+//     {"$ref": "#/definitions/Response"},
+//     {
+//       "type": "object",
+//       "description": "Response to `setInstructionBreakpoints` request",
+//       "properties": {
+//         "body": {
+//           "type": "object",
+//           "properties": {
+//             "breakpoints": {
+//               "type": "array",
+//               "items": {"$ref": "#/definitions/Breakpoint"},
+//               "description":
+//                   "Information about the breakpoints. The array elements
+//                   " "correspond to the elements of the `breakpoints`
+//                   array."
 //             }
 //           },
-//           "required" : ["body"]
+//           "required": ["breakpoints"]
 //         }
-//       ]
-//     },
-// "InstructionBreakpoint" : {
-//   "type" : "object",
-//   "description" : "Properties of a breakpoint passed to the "
+//       },
+//       "required": ["body"]
+//     }
+//   ]
+// },
+// "InstructionBreakpoint": {
+//   "type": "object",
+//   "description": "Properties of a breakpoint passed to the "
 //                   "`setInstructionBreakpoints` request",
-//   "properties" : {
-//     "instructionReference" : {
-//       "type" : "string",
+//   "properties": {
+//     "instructionReference": {
+//       "type": "string",
 //       "description" :
 //           "The instruction reference of the breakpoint.\nThis should be a "
 //           "memory or instruction pointer reference from an
 //           `EvaluateResponse`, "
 //           "`Variable`, `StackFrame`, `GotoTarget`, or `Breakpoint`."
 //     },
-//     "offset" : {
-//       "type" : "integer",
-//       "description" : "The offset from the instruction reference in "
+//     "offset": {
+//       "type": "integer",
+//       "description": "The offset from the instruction reference in "
 //                       "bytes.\nThis can be negative."
 //     },
-//     "condition" : {
-//       "type" : "string",
-//       "description" : "An expression for conditional breakpoints.\nIt is only
+//     "condition": {
+//       "type": "string",
+//       "description": "An expression for conditional breakpoints.\nIt is only
 //       "
 //                       "honored by a debug adapter if the corresponding "
 //                       "capability `supportsConditionalBreakpoints` is true."
 //     },
-//     "hitCondition" : {
-//       "type" : "string",
-//       "description" : "An expression that controls how many hits of the "
+//     "hitCondition": {
+//       "type": "string",
+//       "description": "An expression that controls how many hits of the "
 //                       "breakpoint are ignored.\nThe debug adapter is expected
 //                       " "to interpret the expression as needed.\nThe
 //                       attribute " "is only honored by a debug adapter if the
 //                       corresponding " "capability
 //                       `supportsHitConditionalBreakpoints` is true."
 //     },
-//     "mode" : {
-//       "type" : "string",
-//       "description" : "The mode of this breakpoint. If defined, this must be
+//     "mode": {
+//       "type": "string",
+//       "description": "The mode of this breakpoint. If defined, this must be
 //       "
 //                       "one of the `breakpointModes` the debug adapter "
 //                       "advertised in its `Capabilities`."
 //     }
 //   },
-//   "required" : ["instructionReference"]
+//   "required": ["instructionReference"]
 // },
-// "Breakpoint"
-//     : {
-//       "type" : "object",
+// "Breakpoint": {
+//   "type": "object",
+//   "description" :
+//       "Information about a breakpoint created in `setBreakpoints`, "
+//       "`setFunctionBreakpoints`, `setInstructionBreakpoints`, or "
+//       "`setDataBreakpoints` requests.",
+//   "properties": {
+//     "id": {
+//       "type": "integer",
 //       "description" :
-//           "Information about a breakpoint created in `setBreakpoints`, "
-//           "`setFunctionBreakpoints`, `setInstructionBreakpoints`, or "
-//           "`setDataBreakpoints` requests.",
-//       "properties" : {
-//         "id" : {
-//           "type" : "integer",
-//           "description" :
-//               "The identifier for the breakpoint. It is needed if breakpoint
-//               " "events are used to update or remove breakpoints."
-//         },
-//         "verified" : {
-//           "type" : "boolean",
-//           "description" : "If true, the breakpoint could be set (but not "
-//                           "necessarily at the desired location)."
-//         },
-//         "message" : {
-//           "type" : "string",
-//           "description" : "A message about the state of the breakpoint.\nThis
-//           "
-//                           "is shown to the user and can be used to explain
-//                           why " "a breakpoint could not be verified."
-//         },
-//         "source" : {
-//           "$ref" : "#/definitions/Source",
-//           "description" : "The source where the breakpoint is located."
-//         },
-//         "line" : {
-//           "type" : "integer",
-//           "description" :
-//               "The start line of the actual range covered by the breakpoint."
-//         },
-//         "column" : {
-//           "type" : "integer",
-//           "description" :
-//               "Start position of the source range covered by the breakpoint.
-//               " "It is measured in UTF-16 code units and the client
-//               capability "
-//               "`columnsStartAt1` determines whether it is 0- or 1-based."
-//         },
-//         "endLine" : {
-//           "type" : "integer",
-//           "description" :
-//               "The end line of the actual range covered by the breakpoint."
-//         },
-//         "endColumn" : {
-//           "type" : "integer",
-//           "description" :
-//               "End position of the source range covered by the breakpoint. It
-//               " "is measured in UTF-16 code units and the client capability "
-//               "`columnsStartAt1` determines whether it is 0- or 1-based.\nIf
-//               " "no end line is given, then the end column is assumed to be
-//               in " "the start line."
-//         },
-//         "instructionReference" : {
-//           "type" : "string",
-//           "description" : "A memory reference to where the breakpoint is
-//           set."
-//         },
-//         "offset" : {
-//           "type" : "integer",
-//           "description" : "The offset from the instruction reference.\nThis "
-//                           "can be negative."
-//         },
-//         "reason" : {
-//           "type" : "string",
-//           "description" :
-//               "A machine-readable explanation of why a breakpoint may not be
-//               " "verified. If a breakpoint is verified or a specific reason
-//               is " "not known, the adapter should omit this property.
-//               Possible " "values include:\n\n- `pending`: Indicates a
-//               breakpoint might be " "verified in the future, but the adapter
-//               cannot verify it in the " "current state.\n - `failed`:
-//               Indicates a breakpoint was not " "able to be verified, and the
-//               adapter does not believe it can be " "verified without
-//               intervention.",
-//           "enum" : [ "pending", "failed" ]
-//         }
-//       },
-//       "required" : ["verified"]
+//           "The identifier for the breakpoint. It is needed if breakpoint
+//           " "events are used to update or remove breakpoints."
 //     },
-
+//     "verified": {
+//       "type": "boolean",
+//       "description": "If true, the breakpoint could be set (but not "
+//                       "necessarily at the desired location)."
+//     },
+//     "message": {
+//       "type": "string",
+//       "description": "A message about the state of the breakpoint.\nThis
+//       "
+//                       "is shown to the user and can be used to explain
+//                       why " "a breakpoint could not be verified."
+//     },
+//     "source": {
+//       "$ref": "#/definitions/Source",
+//       "description": "The source where the breakpoint is located."
+//     },
+//     "line": {
+//       "type": "integer",
+//       "description" :
+//           "The start line of the actual range covered by the breakpoint."
+//     },
+//     "column": {
+//       "type": "integer",
+//       "description" :
+//           "Start position of the source range covered by the breakpoint.
+//           " "It is measured in UTF-16 code units and the client
+//           capability "
+//           "`columnsStartAt1` determines whether it is 0- or 1-based."
+//     },
+//     "endLine": {
+//       "type": "integer",
+//       "description" :
+//           "The end line of the actual range covered by the breakpoint."
+//     },
+//     "endColumn": {
+//       "type": "integer",
+//       "description" :
+//           "End position of the source range covered by the breakpoint. It
+//           " "is measured in UTF-16 code units and the client capability "
+//           "`columnsStartAt1` determines whether it is 0- or 1-based.\nIf
+//           " "no end line is given, then the end column is assumed to be
+//           in " "the start line."
+//     },
+//     "instructionReference": {
+//       "type": "string",
+//       "description": "A memory reference to where the breakpoint is
+//       set."
+//     },
+//     "offset": {
+//       "type": "integer",
+//       "description": "The offset from the instruction reference.\nThis "
+//                       "can be negative."
+//     },
+//     "reason": {
+//       "type": "string",
+//       "description" :
+//           "A machine-readable explanation of why a breakpoint may not be
+//           " "verified. If a breakpoint is verified or a specific reason
+//           is " "not known, the adapter should omit this property.
+//           Possible " "values include:\n\n- `pending`: Indicates a
+//           breakpoint might be " "verified in the future, but the adapter
+//           cannot verify it in the " "current state.\n - `failed`:
+//           Indicates a breakpoint was not " "able to be verified, and the
+//           adapter does not believe it can be " "verified without
+//           intervention.",
+//       "enum": [ "pending", "failed" ]
+//     }
+//   },
+//   "required": ["verified"]
+// },
 void request_setInstructionBreakpoints(const llvm::json::Object &request) {
   llvm::json::Object response;
   llvm::json::Array response_breakpoints;
   llvm::json::Object body;
   FillResponse(request, response);
 
-  auto arguments = request.getObject("arguments");
-  auto breakpoints = arguments->getArray("breakpoints");
+  const auto *arguments = request.getObject("arguments");
+  const auto *breakpoints = arguments->getArray("breakpoints");
 
-  // It holds active instruction breakpoint list received from DAP.
-  InstructionBreakpointMap request_ibp;
-  if (breakpoints) {
-    for (const auto &bp : *breakpoints) {
-      auto bp_obj = bp.getAsObject();
-      if (bp_obj) {
-        // Read instruction breakpoint request.
-        InstructionBreakpoint inst_bp(*bp_obj);
-        // Store them into map for reference.
-        request_ibp[inst_bp.instructionAddressReference] = std::move(inst_bp);
-      }
-    }
+  // Disable any instruction breakpoints that aren't in this request.
+  // There is no call to remove instruction breakpoints other than calling this
+  // function with a smaller or empty "breakpoints" list.
+  llvm::SetVector<lldb::addr_t> seen;
+  for (const auto &addr : g_dap.instruction_breakpoints)
+    seen.insert(addr.first);
 
-    // Iterate previous active instruction breakpoint list.
-    for (auto &prev_ibp : g_dap.instruction_breakpoints) {
-      // Find previous instruction breakpoint reference address in newly
-      // received instruction breakpoint list.
-      auto inst_reference = request_ibp.find(prev_ibp.first);
-      // Request for remove and delete the breakpoint, if the prev instruction
-      // breakpoint ID is not available in active instrcation breakpoint list.
-      // Means delete removed breakpoint instance.
-      if (inst_reference == request_ibp.end()) {
-        g_dap.target.BreakpointDelete(prev_ibp.second.id);
-        // Update Prev instruction breakpoint list.
-        g_dap.instruction_breakpoints.erase(prev_ibp.first);
-      } else {
-        // Instead of recreating breakpoint instance, update the breakpoint if
-        // there are any conditional changes.
-        prev_ibp.second.UpdateBreakpoint(inst_reference->second);
-        request_ibp.erase(inst_reference);
-        response_breakpoints.emplace_back(
-            CreateInstructionBreakpoint(&prev_ibp.second));
-      }
+  for (const auto &bp : *breakpoints) {
+    const auto *bp_obj = bp.getAsObject();
+    if (!bp_obj)
+      continue;
+    // Read instruction breakpoint request.
+    InstructionBreakpoint inst_bp(g_dap, *bp_obj);
+    const auto [kv, inserted] = g_dap.instruction_breakpoints.try_emplace(
+        inst_bp.instructionAddressReference, g_dap, *bp_obj);
+    if (inserted) {
+      kv->second.SetBreakpoint();
+    } else {
+      kv->second.UpdateBreakpoint(inst_bp);
     }
+    AppendBreakpoint(&kv->second, response_breakpoints);
+    seen.remove(inst_bp.instructionAddressReference);
+  }
 
-    for (auto &req_bpi : request_ibp) {
-      // Add this breakpoint info to the response
-      g_dap.instruction_breakpoints[req_bpi.first] = std::move(req_bpi.second);
-      InstructionBreakpoint &new_bp =
-          g_dap.instruction_breakpoints[req_bpi.first];
-      new_bp.SetInstructionBreakpoint();
-      response_breakpoints.emplace_back(CreateInstructionBreakpoint(&new_bp));
-    }
+  for (const auto &addr : seen) {
+    auto inst_bp = g_dap.instruction_breakpoints.find(addr);
+    if (inst_bp == g_dap.instruction_breakpoints.end())
+      continue;
+    g_dap.target.BreakpointDelete(inst_bp->second.bp.GetID());
+    g_dap.instruction_breakpoints.erase(addr);
   }
 
   body.try_emplace("breakpoints", std::move(response_breakpoints));

>From 608d66aa99e7c2854f82209a94f97733a97a9b51 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Wed, 6 Nov 2024 16:38:43 -0800
Subject: [PATCH 2/2] Correcting the #include order to match
 https://llvm.org/docs/CodingStandards.html\#include-style

---
 lldb/tools/lldb-dap/Breakpoint.cpp          |  5 +-
 lldb/tools/lldb-dap/Breakpoint.h            |  4 +-
 lldb/tools/lldb-dap/BreakpointBase.cpp      |  1 +
 lldb/tools/lldb-dap/BreakpointBase.h        |  4 +-
 lldb/tools/lldb-dap/ExceptionBreakpoint.cpp |  2 +-
 lldb/tools/lldb-dap/ExceptionBreakpoint.h   |  4 +-
 lldb/tools/lldb-dap/InstructionBreakpoint.h |  6 +-
 lldb/tools/lldb-dap/JSONUtils.cpp           | 26 ++++-----
 lldb/tools/lldb-dap/JSONUtils.h             |  3 +
 lldb/tools/lldb-dap/SourceBreakpoint.cpp    |  1 +
 lldb/tools/lldb-dap/SourceBreakpoint.h      |  1 +
 lldb/tools/lldb-dap/Watchpoint.cpp          |  4 +-
 lldb/tools/lldb-dap/Watchpoint.h            |  4 +-
 lldb/tools/lldb-dap/lldb-dap.cpp            | 65 +++++++++++----------
 14 files changed, 68 insertions(+), 62 deletions(-)

diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp
index aee2f87e2cc23e..ea58b556229e24 100644
--- a/lldb/tools/lldb-dap/Breakpoint.cpp
+++ b/lldb/tools/lldb-dap/Breakpoint.cpp
@@ -8,12 +8,11 @@
 
 #include "Breakpoint.h"
 
+#include "JSONUtils.h"
+
 #include "lldb/API/SBBreakpointLocation.h"
 #include "llvm/ADT/StringExtras.h"
 
-#include "DAP.h"
-#include "JSONUtils.h"
-
 using namespace lldb_dap;
 
 void Breakpoint::SetCondition() { bp.SetCondition(condition.c_str()); }
diff --git a/lldb/tools/lldb-dap/Breakpoint.h b/lldb/tools/lldb-dap/Breakpoint.h
index cffeb2fab1f0ef..d0519ed0c31477 100644
--- a/lldb/tools/lldb-dap/Breakpoint.h
+++ b/lldb/tools/lldb-dap/Breakpoint.h
@@ -9,10 +9,10 @@
 #ifndef LLDB_TOOLS_LLDB_DAP_BREAKPOINT_H
 #define LLDB_TOOLS_LLDB_DAP_BREAKPOINT_H
 
-#include "lldb/API/SBBreakpoint.h"
-
 #include "BreakpointBase.h"
 
+#include "lldb/API/SBBreakpoint.h"
+
 namespace lldb_dap {
 
 struct Breakpoint : public BreakpointBase {
diff --git a/lldb/tools/lldb-dap/BreakpointBase.cpp b/lldb/tools/lldb-dap/BreakpointBase.cpp
index c5d7a9778df018..0c824609b343ca 100644
--- a/lldb/tools/lldb-dap/BreakpointBase.cpp
+++ b/lldb/tools/lldb-dap/BreakpointBase.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "BreakpointBase.h"
+
 #include "JSONUtils.h"
 
 using namespace lldb_dap;
diff --git a/lldb/tools/lldb-dap/BreakpointBase.h b/lldb/tools/lldb-dap/BreakpointBase.h
index bb660ddc451bd5..7e998185ba45a4 100644
--- a/lldb/tools/lldb-dap/BreakpointBase.h
+++ b/lldb/tools/lldb-dap/BreakpointBase.h
@@ -9,11 +9,11 @@
 #ifndef LLDB_TOOLS_LLDB_DAP_BREAKPOINTBASE_H
 #define LLDB_TOOLS_LLDB_DAP_BREAKPOINTBASE_H
 
-#include <string>
+#include "DAPForward.h"
 
 #include "llvm/Support/JSON.h"
 
-#include "DAPForward.h"
+#include <string>
 
 namespace lldb_dap {
 
diff --git a/lldb/tools/lldb-dap/ExceptionBreakpoint.cpp b/lldb/tools/lldb-dap/ExceptionBreakpoint.cpp
index e9bb11face49df..1223d049800aa8 100644
--- a/lldb/tools/lldb-dap/ExceptionBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/ExceptionBreakpoint.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "ExceptionBreakpoint.h"
-#include "BreakpointBase.h"
+
 #include "DAP.h"
 
 namespace lldb_dap {
diff --git a/lldb/tools/lldb-dap/ExceptionBreakpoint.h b/lldb/tools/lldb-dap/ExceptionBreakpoint.h
index 7819bea726a1d0..4b4ba50a11d26c 100644
--- a/lldb/tools/lldb-dap/ExceptionBreakpoint.h
+++ b/lldb/tools/lldb-dap/ExceptionBreakpoint.h
@@ -9,11 +9,11 @@
 #ifndef LLDB_TOOLS_LLDB_DAP_EXCEPTIONBREAKPOINT_H
 #define LLDB_TOOLS_LLDB_DAP_EXCEPTIONBREAKPOINT_H
 
-#include <string>
+#include "DAPForward.h"
 
 #include "lldb/API/SBBreakpoint.h"
 
-#include "DAPForward.h"
+#include <string>
 
 namespace lldb_dap {
 
diff --git a/lldb/tools/lldb-dap/InstructionBreakpoint.h b/lldb/tools/lldb-dap/InstructionBreakpoint.h
index cc251c96f5bdd8..b514176008fad5 100644
--- a/lldb/tools/lldb-dap/InstructionBreakpoint.h
+++ b/lldb/tools/lldb-dap/InstructionBreakpoint.h
@@ -10,12 +10,12 @@
 #ifndef LLDB_TOOLS_LLDB_DAP_INSTRUCTIONBREAKPOINT_H
 #define LLDB_TOOLS_LLDB_DAP_INSTRUCTIONBREAKPOINT_H
 
-#include <cstdint>
+#include "Breakpoint.h"
+#include "DAPForward.h"
 
 #include "lldb/lldb-types.h"
 
-#include "Breakpoint.h"
-#include "DAPForward.h"
+#include <cstdint>
 
 namespace lldb_dap {
 
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 70bebddc91119d..d9e558fd2268f1 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -6,27 +6,27 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <iomanip>
-#include <optional>
-#include <sstream>
-#include <string.h>
+#include "JSONUtils.h"
 
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/ScopedPrinter.h"
+#include "DAP.h"
+#include "ExceptionBreakpoint.h"
+#include "LLDBUtils.h"
 
 #include "lldb/API/SBDeclaration.h"
 #include "lldb/API/SBStream.h"
 #include "lldb/API/SBStringList.h"
 #include "lldb/API/SBStructuredData.h"
 #include "lldb/API/SBValue.h"
-#include "lldb/Host/PosixApi.h"
 
-#include "DAP.h"
-#include "ExceptionBreakpoint.h"
-#include "JSONUtils.h"
-#include "LLDBUtils.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+#include <iomanip>
+#include <optional>
+#include <sstream>
+#include <string.h>
 
 namespace lldb_dap {
 
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index 43056f3dc14566..14fe174c048619 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -11,9 +11,12 @@
 
 #include "BreakpointBase.h"
 #include "DAPForward.h"
+
 #include "lldb/API/SBModule.h"
+
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/JSON.h"
+
 #include <cstdint>
 #include <optional>
 #include <unordered_map>
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
index 7415a0914dad43..b44aa4eb8ab6a0 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SourceBreakpoint.h"
+
 #include "DAP.h"
 #include "JSONUtils.h"
 
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.h b/lldb/tools/lldb-dap/SourceBreakpoint.h
index 113c0efbddcc5c..e8380f1fe7fd55 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.h
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.h
@@ -10,6 +10,7 @@
 #define LLDB_TOOLS_LLDB_DAP_SOURCEBREAKPOINT_H
 
 #include "Breakpoint.h"
+
 #include "llvm/ADT/StringRef.h"
 
 namespace lldb_dap {
diff --git a/lldb/tools/lldb-dap/Watchpoint.cpp b/lldb/tools/lldb-dap/Watchpoint.cpp
index 56dd5434269151..c6eae3e773c7bd 100644
--- a/lldb/tools/lldb-dap/Watchpoint.cpp
+++ b/lldb/tools/lldb-dap/Watchpoint.cpp
@@ -8,11 +8,11 @@
 
 #include "Watchpoint.h"
 
-#include "llvm/ADT/StringExtras.h"
-
 #include "DAP.h"
 #include "JSONUtils.h"
 
+#include "llvm/ADT/StringExtras.h"
+
 namespace lldb_dap {
 Watchpoint::Watchpoint(DAP &d, const llvm::json::Object &obj)
     : BreakpointBase(d, obj) {
diff --git a/lldb/tools/lldb-dap/Watchpoint.h b/lldb/tools/lldb-dap/Watchpoint.h
index b84b4b1c9ff3d3..b3f68282c0b722 100644
--- a/lldb/tools/lldb-dap/Watchpoint.h
+++ b/lldb/tools/lldb-dap/Watchpoint.h
@@ -9,12 +9,12 @@
 #ifndef LLDB_TOOLS_LLDB_DAP_WATCHPOINT_H
 #define LLDB_TOOLS_LLDB_DAP_WATCHPOINT_H
 
+#include "BreakpointBase.h"
+
 #include "lldb/API/SBError.h"
 #include "lldb/API/SBWatchpoint.h"
 #include "lldb/API/SBWatchpointOptions.h"
 
-#include "BreakpointBase.h"
-
 namespace lldb_dap {
 
 struct Watchpoint : public BreakpointBase {
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index 525cb2d5eddab5..f902626d33c3b7 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -6,6 +6,39 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "DAP.h"
+#include "FifoFiles.h"
+#include "JSONUtils.h"
+#include "LLDBUtils.h"
+#include "OutputRedirector.h"
+#include "RunInTerminal.h"
+#include "Watchpoint.h"
+
+#include "lldb/API/SBDeclaration.h"
+#include "lldb/API/SBInstruction.h"
+#include "lldb/API/SBListener.h"
+#include "lldb/API/SBMemoryRegionInfo.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/API/SBStringList.h"
+#include "lldb/Host/Config.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/Base64.h"
+#include "llvm/Support/Errno.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+
 #include <cassert>
 #include <climits>
 #include <cstdarg>
@@ -43,38 +76,6 @@
 #include <thread>
 #include <vector>
 
-#include "lldb/API/SBDeclaration.h"
-#include "lldb/API/SBInstruction.h"
-#include "lldb/API/SBListener.h"
-#include "lldb/API/SBMemoryRegionInfo.h"
-#include "lldb/API/SBStream.h"
-#include "lldb/API/SBStringList.h"
-#include "lldb/Host/Config.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/ScopeExit.h"
-#include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Option/OptTable.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/Base64.h"
-#include "llvm/Support/Errno.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include "DAP.h"
-#include "FifoFiles.h"
-#include "JSONUtils.h"
-#include "LLDBUtils.h"
-#include "OutputRedirector.h"
-#include "RunInTerminal.h"
-#include "Watchpoint.h"
-
 #if defined(_WIN32)
 #ifndef PATH_MAX
 #define PATH_MAX MAX_PATH



More information about the lldb-commits mailing list