yinghuitan updated this revision to Diff 355437.
yinghuitan added a comment.

rebase to latest master


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105166/new/

https://reviews.llvm.org/D105166

Files:
  lldb/tools/lldb-vscode/VSCode.cpp
  lldb/tools/lldb-vscode/VSCode.h
  lldb/tools/lldb-vscode/lldb-vscode.cpp

Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===================================================================
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -107,6 +107,19 @@
 
 enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
 
+lldb::SBValueList *GetTopLevelScope(int64_t variablesReference) {
+  switch (variablesReference) {
+  case VARREF_LOCALS:
+    return &g_vsc.variables.locals;
+  case VARREF_GLOBALS:
+    return &g_vsc.variables.globals;
+  case VARREF_REGS:
+    return &g_vsc.variables.registers;
+  default:
+    return nullptr;
+  }
+}
+
 SOCKET AcceptConnection(int portno) {
   // Accept a socket connection from any host on "portno".
   SOCKET newsockfd = -1;
@@ -727,6 +740,7 @@
   // Remember the thread ID that caused the resume so we can set the
   // "threadCausedFocus" boolean value in the "stopped" events.
   g_vsc.focus_tid = GetUnsigned(arguments, "threadId", LLDB_INVALID_THREAD_ID);
+  g_vsc.willContinue();
   lldb::SBError error = process.Continue();
   llvm::json::Object body;
   body.try_emplace("allThreadsContinued", true);
@@ -1215,9 +1229,9 @@
       EmplaceSafeString(body, "type",
                         value_typename ? value_typename : NO_TYPENAME);
       if (value.MightHaveChildren()) {
-        auto variablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
-        g_vsc.variables.Append(value);
-        body.try_emplace("variablesReference", variablesReference);
+        auto variableReference = g_vsc.variables.InsertNewExpandableVariable(
+            value, /*is_permanent=*/context == "repl");
+        body.try_emplace("variablesReference", variableReference);
       } else {
         body.try_emplace("variablesReference", (int64_t)0);
       }
@@ -1769,6 +1783,7 @@
     // Remember the thread ID that caused the resume so we can set the
     // "threadCausedFocus" boolean value in the "stopped" events.
     g_vsc.focus_tid = thread.GetThreadID();
+    g_vsc.willContinue();
     thread.StepOver();
   } else {
     response["success"] = llvm::json::Value(false);
@@ -1895,20 +1910,15 @@
     frame.GetThread().GetProcess().SetSelectedThread(frame.GetThread());
     frame.GetThread().SetSelectedFrame(frame.GetFrameID());
   }
-  g_vsc.variables.Clear();
-  g_vsc.variables.Append(frame.GetVariables(true,   // arguments
-                                            true,   // locals
-                                            false,  // statics
-                                            true)); // in_scope_only
-  g_vsc.num_locals = g_vsc.variables.GetSize();
-  g_vsc.variables.Append(frame.GetVariables(false,  // arguments
-                                            false,  // locals
-                                            true,   // statics
-                                            true)); // in_scope_only
-  g_vsc.num_globals = g_vsc.variables.GetSize() - (g_vsc.num_locals);
-  g_vsc.variables.Append(frame.GetRegisters());
-  g_vsc.num_regs =
-      g_vsc.variables.GetSize() - (g_vsc.num_locals + g_vsc.num_globals);
+  g_vsc.variables.locals = frame.GetVariables(/*arguments=*/true,
+                                              /*locals=*/true,
+                                              /*statics=*/false,
+                                              /*in_scope_only=*/true);
+  g_vsc.variables.globals = frame.GetVariables(/*arguments=*/false,
+                                               /*locals=*/false,
+                                               /*statics=*/true,
+                                               /*in_scope_only=*/true);
+  g_vsc.variables.registers = frame.GetRegisters();
   body.try_emplace("scopes", g_vsc.CreateTopLevelScopes());
   response.try_emplace("body", std::move(body));
   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
@@ -2523,6 +2533,7 @@
     // Remember the thread ID that caused the resume so we can set the
     // "threadCausedFocus" boolean value in the "stopped" events.
     g_vsc.focus_tid = thread.GetThreadID();
+    g_vsc.willContinue();
     thread.StepInto();
   } else {
     response["success"] = llvm::json::Value(false);
@@ -2575,6 +2586,7 @@
     // Remember the thread ID that caused the resume so we can set the
     // "threadCausedFocus" boolean value in the "stopped" events.
     g_vsc.focus_tid = thread.GetThreadID();
+    g_vsc.willContinue();
     thread.StepOut();
   } else {
     response["success"] = llvm::json::Value(false);
@@ -2750,37 +2762,19 @@
   // of the variable within the g_vsc.variables list.
   const auto id_value = GetUnsigned(arguments, "id", UINT64_MAX);
   if (id_value != UINT64_MAX) {
-    variable = g_vsc.variables.GetValueAtIndex(id_value);
-  } else if (VARREF_IS_SCOPE(variablesReference)) {
+    variable = g_vsc.variables.GetVariableFromVariableReference(id_value);
+  } else if (lldb::SBValueList *top_scope = GetTopLevelScope(variablesReference)) {
     // variablesReference is one of our scopes, not an actual variable it is
     // asking for a variable in locals or globals or registers
-    int64_t start_idx = 0;
-    int64_t end_idx = 0;
-    switch (variablesReference) {
-    case VARREF_LOCALS:
-      start_idx = 0;
-      end_idx = start_idx + g_vsc.num_locals;
-      break;
-    case VARREF_GLOBALS:
-      start_idx = g_vsc.num_locals;
-      end_idx = start_idx + g_vsc.num_globals;
-      break;
-    case VARREF_REGS:
-      start_idx = g_vsc.num_locals + g_vsc.num_globals;
-      end_idx = start_idx + g_vsc.num_regs;
-      break;
-    default:
-      break;
-    }
-
-    for (int64_t i = end_idx - 1; i >= start_idx; --i) {
-      lldb::SBValue curr_variable = g_vsc.variables.GetValueAtIndex(i);
+    uint32_t end_idx = top_scope->GetSize();
+    for (uint32_t i = 0; i < end_idx; ++i) {
+      lldb::SBValue curr_variable = top_scope->GetValueAtIndex(i);
       std::string variable_name = CreateUniqueVariableNameForDisplay(
           curr_variable, is_duplicated_variable_name);
       if (variable_name == name) {
         variable = curr_variable;
         if (curr_variable.MightHaveChildren())
-          newVariablesReference = i;
+          newVariablesReference = g_vsc.variables.GetNewVariableRefence(true);
         break;
       }
     }
@@ -2790,8 +2784,8 @@
 
     // We have a named item within an actual variable so we need to find it
     // withing the container variable by name.
-    const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
-    lldb::SBValue container = g_vsc.variables.GetValueAtIndex(var_idx);
+    lldb::SBValue container =
+        g_vsc.variables.GetVariableFromVariableReference(variablesReference);
     variable = container.GetChildMemberWithName(name.data());
     if (!variable.IsValid()) {
       if (name.startswith("[")) {
@@ -2807,8 +2801,9 @@
     // We don't know the index of the variable in our g_vsc.variables
     if (variable.IsValid()) {
       if (variable.MightHaveChildren()) {
-        newVariablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
-        g_vsc.variables.Append(variable);
+        auto is_permanent =
+            g_vsc.variables.IsPermanentVariableReference(variablesReference);
+        g_vsc.variables.InsertNewExpandableVariable(variable, is_permanent);
       }
     }
   }
@@ -2919,33 +2914,19 @@
   if (format)
     hex = GetBoolean(format, "hex", false);
 
-  if (VARREF_IS_SCOPE(variablesReference)) {
+  if (lldb::SBValueList *top_scope = GetTopLevelScope(variablesReference)) {
     // variablesReference is one of our scopes, not an actual variable it is
     // asking for the list of args, locals or globals.
     int64_t start_idx = 0;
     int64_t num_children = 0;
-    switch (variablesReference) {
-    case VARREF_LOCALS:
-      start_idx = start;
-      num_children = g_vsc.num_locals;
-      break;
-    case VARREF_GLOBALS:
-      start_idx = start + g_vsc.num_locals + start;
-      num_children = g_vsc.num_globals;
-      break;
-    case VARREF_REGS:
-      start_idx = start + g_vsc.num_locals + g_vsc.num_globals;
-      num_children = g_vsc.num_regs;
-      break;
-    default:
-      break;
-    }
+
+    num_children = top_scope->GetSize();
     const int64_t end_idx = start_idx + ((count == 0) ? num_children : count);
 
     // We first find out which variable names are duplicated
     std::map<std::string, int> variable_name_counts;
     for (auto i = start_idx; i < end_idx; ++i) {
-      lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(i);
+      lldb::SBValue variable = top_scope->GetValueAtIndex(i);
       if (!variable.IsValid())
         break;
       variable_name_counts[GetNonNullVariableName(variable)]++;
@@ -2953,19 +2934,25 @@
 
     // Now we construct the result with unique display variable names
     for (auto i = start_idx; i < end_idx; ++i) {
-      lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(i);
+      lldb::SBValue variable = top_scope->GetValueAtIndex(i);
 
       if (!variable.IsValid())
         break;
-      variables.emplace_back(CreateVariable(variable, VARIDX_TO_VARREF(i), i,
-                                            hex,
+
+      int64_t var_ref = 0;
+      if (variable.MightHaveChildren()) {
+        var_ref = g_vsc.variables.InsertNewExpandableVariable(
+            variable, /*is_permanent=*/false);
+      }
+      variables.emplace_back(CreateVariable(
+          variable, var_ref, var_ref != 0 ? var_ref : UINT64_MAX, hex,
           variable_name_counts[GetNonNullVariableName(variable)] > 1));
     }
   } else {
     // We are expanding a variable that has children, so we will return its
     // children.
-    const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
-    lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(var_idx);
+    lldb::SBValue variable =
+        g_vsc.variables.GetVariableFromVariableReference(variablesReference);
     if (variable.IsValid()) {
       const auto num_children = variable.GetNumChildren();
       const int64_t end_idx = start + ((count == 0) ? num_children : count);
@@ -2974,11 +2961,12 @@
         if (!child.IsValid())
           break;
         if (child.MightHaveChildren()) {
-          const int64_t var_idx = g_vsc.variables.GetSize();
-          auto childVariablesReferences = VARIDX_TO_VARREF(var_idx);
-          variables.emplace_back(
-              CreateVariable(child, childVariablesReferences, var_idx, hex));
-          g_vsc.variables.Append(child);
+          auto is_permanent =
+              g_vsc.variables.IsPermanentVariableReference(variablesReference);
+          auto childVariablesReferences =
+              g_vsc.variables.InsertNewExpandableVariable(child, is_permanent);
+          variables.emplace_back(CreateVariable(child, childVariablesReferences,
+                                                childVariablesReferences, hex));
         } else {
           variables.emplace_back(CreateVariable(child, 0, INT64_MAX, hex));
         }
Index: lldb/tools/lldb-vscode/VSCode.h
===================================================================
--- lldb/tools/lldb-vscode/VSCode.h
+++ lldb/tools/lldb-vscode/VSCode.h
@@ -58,9 +58,6 @@
 #define VARREF_GLOBALS (int64_t)2
 #define VARREF_REGS (int64_t)3
 #define VARREF_FIRST_VAR_IDX (int64_t)4
-#define VARREF_IS_SCOPE(v) (VARREF_LOCALS <= 1 && v < VARREF_FIRST_VAR_IDX)
-#define VARIDX_TO_VARREF(i) ((i) + VARREF_FIRST_VAR_IDX)
-#define VARREF_TO_VARIDX(v) ((v)-VARREF_FIRST_VAR_IDX)
 #define NO_TYPENAME "<no-type>"
 
 namespace lldb_vscode {
@@ -83,17 +80,48 @@
   JSONNotObject
 };
 
+struct Variables {
+  // Bit mask to tell if a variableReference is inside
+  // expandable_permanent_variables or not.
+  static constexpr int64_t PermanentVariableBitMask = (1ll << 32);
+
+  lldb::SBValueList locals;
+  lldb::SBValueList globals;
+  lldb::SBValueList registers;
+
+  int64_t next_temporary_var_ref{VARREF_FIRST_VAR_IDX};
+  int64_t next_permanent_var_ref{VARREF_FIRST_VAR_IDX};
+  llvm::DenseMap<int64_t, lldb::SBValue> expandable_variables;
+  llvm::DenseMap<int64_t, lldb::SBValue> expandable_permanent_variables;
+
+  /// Check if \p variableReference points to variable in a
+  /// expandable_permanent_variables.
+  bool IsPermanentVariableReference(int64_t variableReference);
+
+  /// \return a new variableReference. If is_permanent is true the returned
+  /// value will have the PermanentVariableBitMask bit set.
+  int64_t GetNewVariableRefence(bool is_permanent);
+
+  /// \return the expandable variable corresponding with variableReference value
+  /// of \p value.
+  lldb::SBValue GetVariableFromVariableReference(int64_t var_ref);
+
+  /// Insert a new \p expandableVariable.
+  int64_t InsertNewExpandableVariable(lldb::SBValue expandableVariable,
+                                      bool is_permanent);
+
+  /// Clear all scope variables and non-permanent expandable variables.
+  void Clear();
+};
+
 struct VSCode {
   std::string debug_adaptor_path;
   InputStream input;
   OutputStream output;
   lldb::SBDebugger debugger;
   lldb::SBTarget target;
-  lldb::SBValueList variables;
+  Variables variables;
   lldb::SBBroadcaster broadcaster;
-  int64_t num_regs;
-  int64_t num_locals;
-  int64_t num_globals;
   std::thread event_thread;
   std::thread progress_event_thread;
   std::unique_ptr<std::ofstream> log;
@@ -206,6 +234,9 @@
   ///     IDE.
   void RegisterRequestCallback(std::string request, RequestCallback callback);
 
+  /// Debuggee will continue from stopped state.
+  void willContinue() { variables.Clear(); }
+
 private:
   // Send the JSON in "json_str" to the "out" stream. Correctly send the
   // "Content-Length:" field followed by the length, followed by the raw
Index: lldb/tools/lldb-vscode/VSCode.cpp
===================================================================
--- lldb/tools/lldb-vscode/VSCode.cpp
+++ lldb/tools/lldb-vscode/VSCode.cpp
@@ -30,8 +30,7 @@
 VSCode g_vsc;
 
 VSCode::VSCode()
-    : variables(), broadcaster("lldb-vscode"), num_regs(0), num_locals(0),
-      num_globals(0), log(),
+    : broadcaster("lldb-vscode"),
       exception_breakpoints(
           {{"cpp_catch", "C++ Catch", lldb::eLanguageTypeC_plus_plus},
            {"cpp_throw", "C++ Throw", lldb::eLanguageTypeC_plus_plus},
@@ -382,10 +381,12 @@
 
 llvm::json::Value VSCode::CreateTopLevelScopes() {
   llvm::json::Array scopes;
-  scopes.emplace_back(CreateScope("Locals", VARREF_LOCALS, num_locals, false));
-  scopes.emplace_back(
-      CreateScope("Globals", VARREF_GLOBALS, num_globals, false));
-  scopes.emplace_back(CreateScope("Registers", VARREF_REGS, num_regs, false));
+  scopes.emplace_back(CreateScope("Locals", VARREF_LOCALS,
+                                  g_vsc.variables.locals.GetSize(), false));
+  scopes.emplace_back(CreateScope("Globals", VARREF_GLOBALS,
+                                  g_vsc.variables.globals.GetSize(), false));
+  scopes.emplace_back(CreateScope("Registers", VARREF_REGS,
+                                  g_vsc.variables.registers.GetSize(), false));
   return llvm::json::Value(std::move(scopes));
 }
 
@@ -527,4 +528,43 @@
   request_handlers[request] = callback;
 }
 
+void Variables::Clear() {
+  locals.Clear();
+  globals.Clear();
+  registers.Clear();
+  expandable_variables.clear();
+}
+
+int64_t Variables::GetNewVariableRefence(bool is_permanent) {
+  if (is_permanent)
+    return PermanentVariableBitMask | next_permanent_var_ref++;
+  else
+    return next_temporary_var_ref++;
+}
+
+bool Variables::IsPermanentVariableReference(int64_t var_ref) {
+  return (var_ref & PermanentVariableBitMask) != 0;
+}
+
+lldb::SBValue Variables::GetVariableFromVariableReference(int64_t var_ref) {
+  lldb::SBValue variable;
+  if (IsPermanentVariableReference(var_ref))
+    variable = expandable_permanent_variables.find(var_ref)->second;
+  else
+    variable = expandable_variables.find(var_ref)->second;
+  return variable;
+}
+
+int64_t Variables::InsertNewExpandableVariable(lldb::SBValue expandableVariable,
+                                               bool is_permanent) {
+  auto newVariablesReferences = GetNewVariableRefence(is_permanent);
+  if (is_permanent)
+    expandable_permanent_variables.insert(
+        std::make_pair(newVariablesReferences, expandableVariable));
+  else
+    expandable_variables.insert(
+        std::make_pair(newVariablesReferences, expandableVariable));
+  return newVariablesReferences;
+}
+
 } // namespace lldb_vscode
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to