[Lldb-commits] [lldb] r290688 - Fix the variable view in the "gui" curses mode so that variables whose children change will update correctly. Previously the variable view would update the children once and not change. If you were stepping through code where the dynamic type of a variable would change the value and its children, or a synthetic type (like say for a std::vector<int>), the variable view wouldn't update. Now it caches the children and uses the process stop ID to tell when the children need to be updated.

Greg Clayton via lldb-commits lldb-commits at lists.llvm.org
Wed Dec 28 13:22:38 PST 2016


Author: gclayton
Date: Wed Dec 28 15:22:37 2016
New Revision: 290688

URL: http://llvm.org/viewvc/llvm-project?rev=290688&view=rev
Log:
Fix the variable view in the "gui" curses mode so that variables whose children change will update correctly. Previously the variable view would update the children once and not change. If you were stepping through code where the dynamic type of a variable would change the value and its children, or a synthetic type (like say for a std::vector<int>), the variable view wouldn't update. Now it caches the children and uses the process stop ID to tell when the children need to be updated.

Modified:
    lldb/trunk/include/lldb/Core/ValueObject.h
    lldb/trunk/include/lldb/Core/ValueObjectList.h
    lldb/trunk/source/Core/IOHandler.cpp
    lldb/trunk/source/Core/ValueObject.cpp

Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=290688&r1=290687&r2=290688&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Wed Dec 28 15:22:37 2016
@@ -1011,6 +1011,48 @@ private:
   DISALLOW_COPY_AND_ASSIGN(ValueObject);
 };
 
+//------------------------------------------------------------------------------
+// A value object manager class that is seeded with the static variable value
+// and it vends the user facing value object. If the type is dynamic it can
+// vend the dynamic type. If this user type also has a synthetic type associated
+// with it, it will vend the synthetic type. The class watches the process' stop
+// ID and will update the user type when needed.
+//------------------------------------------------------------------------------
+class ValueObjectManager {
+  // The root value object is the static typed variable object.
+  lldb::ValueObjectSP m_root_valobj_sp;
+  // The user value object is the value object the user wants to see.
+  lldb::ValueObjectSP m_user_valobj_sp;
+  lldb::DynamicValueType m_use_dynamic;
+  uint32_t m_stop_id; // The stop ID that m_user_valobj_sp is valid for.
+  bool m_use_synthetic;
+
+public:
+  ValueObjectManager() {}
+  
+  ValueObjectManager(lldb::ValueObjectSP in_valobj_sp,
+                     lldb::DynamicValueType use_dynamic, bool use_synthetic);
+  
+  bool IsValid() const;
+  
+  lldb::ValueObjectSP GetRootSP() const { return m_root_valobj_sp; }
+  
+  // Gets the correct value object from the root object for a given process
+  // stop ID. If dynamic values are enabled, or if synthetic children are
+  // enabled, the value object that the user wants to see might change while
+  // debugging.
+  lldb::ValueObjectSP GetSP();
+  
+  void SetUseDynamic(lldb::DynamicValueType use_dynamic);
+  void SetUseSynthetic(bool use_synthetic);
+  lldb::DynamicValueType GetUseDynamic() const { return m_use_dynamic; }
+  bool GetUseSynthetic() const { return m_use_synthetic; }
+  lldb::TargetSP GetTargetSP() const;
+  lldb::ProcessSP GetProcessSP() const;
+  lldb::ThreadSP GetThreadSP() const;
+  lldb::StackFrameSP GetFrameSP() const;
+};
+
 } // namespace lldb_private
 
 #endif // liblldb_ValueObject_h_

Modified: lldb/trunk/include/lldb/Core/ValueObjectList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectList.h?rev=290688&r1=290687&r2=290688&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectList.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObjectList.h Wed Dec 28 15:22:37 2016
@@ -62,6 +62,9 @@ public:
 
   void Clear() { m_value_objects.clear(); }
 
+  const std::vector<lldb::ValueObjectSP> &GetObjects() const {
+    return m_value_objects;
+  }
 protected:
   typedef std::vector<lldb::ValueObjectSP> collection;
   //------------------------------------------------------------------

Modified: lldb/trunk/source/Core/IOHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/IOHandler.cpp?rev=290688&r1=290687&r2=290688&view=diff
==============================================================================
--- lldb/trunk/source/Core/IOHandler.cpp (original)
+++ lldb/trunk/source/Core/IOHandler.cpp Wed Dec 28 15:22:37 2016
@@ -1905,8 +1905,10 @@ protected:
 using namespace curses;
 
 struct Row {
-  ValueObjectSP valobj;
+  ValueObjectManager value;
   Row *parent;
+  // The process stop ID when the children were calculated.
+  uint32_t children_stop_id;
   int row_idx;
   int x;
   int y;
@@ -1916,8 +1918,8 @@ struct Row {
   std::vector<Row> children;
 
   Row(const ValueObjectSP &v, Row *p)
-      : valobj(v), parent(p), row_idx(0), x(1), y(1),
-        might_have_children(v ? v->MightHaveChildren() : false),
+      : value(v, lldb::eDynamicDontRunTarget, true), parent(p), row_idx(0),
+        x(1), y(1), might_have_children(v ? v->MightHaveChildren() : false),
         expanded(false), calculated_children(false), children() {}
 
   size_t GetDepth() const {
@@ -1928,8 +1930,19 @@ struct Row {
 
   void Expand() {
     expanded = true;
+  }
+
+  std::vector<Row> &GetChildren() {
+    ProcessSP process_sp = value.GetProcessSP();
+    auto stop_id = process_sp->GetStopID();
+    if (process_sp && stop_id != children_stop_id) {
+      children_stop_id = stop_id;
+      calculated_children = false;
+    }
     if (!calculated_children) {
+      children.clear();
       calculated_children = true;
+      ValueObjectSP valobj = value.GetSP();
       if (valobj) {
         const size_t num_children = valobj->GetNumChildren();
         for (size_t i = 0; i < num_children; ++i) {
@@ -1937,9 +1950,14 @@ struct Row {
         }
       }
     }
+    return children;
   }
 
-  void Unexpand() { expanded = false; }
+  void Unexpand() {
+    expanded = false;
+    calculated_children = false;
+    children.clear();
+  }
 
   void DrawTree(Window &window) {
     if (parent)
@@ -1972,7 +1990,7 @@ struct Row {
     if (parent)
       parent->DrawTreeForChild(window, this, reverse_depth + 1);
 
-    if (&children.back() == child) {
+    if (&GetChildren().back() == child) {
       // Last child
       if (reverse_depth == 0) {
         window.PutChar(ACS_LLCORNER);
@@ -2620,12 +2638,12 @@ protected:
 class ValueObjectListDelegate : public WindowDelegate {
 public:
   ValueObjectListDelegate()
-      : m_valobj_list(), m_rows(), m_selected_row(nullptr),
+      : m_rows(), m_selected_row(nullptr),
         m_selected_row_idx(0), m_first_visible_row(0), m_num_rows(0),
         m_max_x(0), m_max_y(0) {}
 
   ValueObjectListDelegate(ValueObjectList &valobj_list)
-      : m_valobj_list(valobj_list), m_rows(), m_selected_row(nullptr),
+      : m_rows(), m_selected_row(nullptr),
         m_selected_row_idx(0), m_first_visible_row(0), m_num_rows(0),
         m_max_x(0), m_max_y(0) {
     SetValues(valobj_list);
@@ -2639,10 +2657,8 @@ public:
     m_first_visible_row = 0;
     m_num_rows = 0;
     m_rows.clear();
-    m_valobj_list = valobj_list;
-    const size_t num_values = m_valobj_list.GetSize();
-    for (size_t i = 0; i < num_values; ++i)
-      m_rows.push_back(Row(m_valobj_list.GetValueObjectAtIndex(i), nullptr));
+    for (auto &valobj_sp : valobj_list.GetObjects())
+      m_rows.push_back(Row(valobj_sp, nullptr));
   }
 
   bool WindowDelegateDraw(Window &window, bool force) override {
@@ -2733,8 +2749,11 @@ public:
     case 'B':
     case 'f':
       // Change the format for the currently selected item
-      if (m_selected_row)
-        m_selected_row->valobj->SetFormat(FormatForChar(c));
+      if (m_selected_row) {
+        auto valobj_sp = m_selected_row->value.GetSP();
+        if (valobj_sp)
+          valobj_sp->SetFormat(FormatForChar(c));
+      }
       return eKeyHandled;
 
     case 't':
@@ -2812,7 +2831,6 @@ public:
   }
 
 protected:
-  ValueObjectList m_valobj_list;
   std::vector<Row> m_rows;
   Row *m_selected_row;
   uint32_t m_selected_row_idx;
@@ -2859,7 +2877,7 @@ protected:
 
   bool DisplayRowObject(Window &window, Row &row, DisplayOptions &options,
                         bool highlight, bool last_child) {
-    ValueObject *valobj = row.valobj.get();
+    ValueObject *valobj = row.value.GetSP().get();
 
     if (valobj == nullptr)
       return false;
@@ -2941,18 +2959,19 @@ protected:
         ++m_num_rows;
       }
 
-      if (row.expanded && !row.children.empty()) {
-        DisplayRows(window, row.children, options);
+      auto &children = row.GetChildren();
+      if (row.expanded && !children.empty()) {
+        DisplayRows(window, children, options);
       }
     }
   }
 
-  int CalculateTotalNumberRows(const std::vector<Row> &rows) {
+  int CalculateTotalNumberRows(std::vector<Row> &rows) {
     int row_count = 0;
-    for (const auto &row : rows) {
+    for (auto &row : rows) {
       ++row_count;
       if (row.expanded)
-        row_count += CalculateTotalNumberRows(row.children);
+        row_count += CalculateTotalNumberRows(row.GetChildren());
     }
     return row_count;
   }
@@ -2963,8 +2982,9 @@ protected:
         return &row;
       else {
         --row_index;
-        if (row.expanded && !row.children.empty()) {
-          Row *result = GetRowForRowIndexImpl(row.children, row_index);
+        auto &children = row.GetChildren();
+        if (row.expanded && !children.empty()) {
+          Row *result = GetRowForRowIndexImpl(children, row_index);
           if (result)
             return result;
         }

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=290688&r1=290687&r2=290688&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Wed Dec 28 15:22:37 2016
@@ -3352,3 +3352,98 @@ void ValueObject::SetSyntheticChildrenGe
 uint64_t ValueObject::GetLanguageFlags() { return m_language_flags; }
 
 void ValueObject::SetLanguageFlags(uint64_t flags) { m_language_flags = flags; }
+
+ValueObjectManager::ValueObjectManager(lldb::ValueObjectSP in_valobj_sp,
+                                       lldb::DynamicValueType use_dynamic,
+                                       bool use_synthetic) : m_root_valobj_sp(),
+    m_user_valobj_sp(), m_use_dynamic(use_dynamic), m_stop_id(UINT32_MAX),
+    m_use_synthetic(use_synthetic) {
+  if (!in_valobj_sp)
+    return;
+  // If the user passes in a value object that is dynamic or synthetic, then
+  // water it down to the static type.
+  m_root_valobj_sp = in_valobj_sp->GetQualifiedRepresentationIfAvailable(lldb::eNoDynamicValues, false);
+}
+
+bool ValueObjectManager::IsValid() const {
+  if (!m_root_valobj_sp)
+    return false;
+  lldb::TargetSP target_sp = GetTargetSP();
+  if (target_sp)
+    return target_sp->IsValid();
+  return false;
+}
+
+lldb::ValueObjectSP ValueObjectManager::GetSP() {
+  lldb::ProcessSP process_sp = GetProcessSP();
+  if (!process_sp)
+    return lldb::ValueObjectSP();
+  
+  const uint32_t current_stop_id = process_sp->GetLastNaturalStopID();
+  if (current_stop_id == m_stop_id)
+    return m_user_valobj_sp;
+  
+  m_stop_id = current_stop_id;
+  
+  if (!m_root_valobj_sp) {
+    m_user_valobj_sp.reset();
+    return m_root_valobj_sp;
+  }
+  
+  m_user_valobj_sp = m_root_valobj_sp;
+  
+  if (m_use_dynamic != lldb::eNoDynamicValues) {
+    lldb::ValueObjectSP dynamic_sp = m_user_valobj_sp->GetDynamicValue(m_use_dynamic);
+    if (dynamic_sp)
+      m_user_valobj_sp = dynamic_sp;
+  }
+  
+  if (m_use_synthetic) {
+    lldb::ValueObjectSP synthetic_sp = m_user_valobj_sp->GetSyntheticValue(m_use_synthetic);
+    if (synthetic_sp)
+      m_user_valobj_sp = synthetic_sp;
+  }
+  
+  return m_user_valobj_sp;
+}
+
+void ValueObjectManager::SetUseDynamic(lldb::DynamicValueType use_dynamic) {
+  if (use_dynamic != m_use_dynamic) {
+    m_use_dynamic = use_dynamic;
+    m_user_valobj_sp.reset();
+    m_stop_id = UINT32_MAX;
+  }
+}
+
+void ValueObjectManager::SetUseSynthetic(bool use_synthetic) {
+  if (m_use_synthetic != use_synthetic) {
+    m_use_synthetic = use_synthetic;
+    m_user_valobj_sp.reset();
+    m_stop_id = UINT32_MAX;
+  }
+}
+
+lldb::TargetSP ValueObjectManager::GetTargetSP() const {
+  if (!m_root_valobj_sp)
+    return m_root_valobj_sp->GetTargetSP();
+  return lldb::TargetSP();
+}
+
+lldb::ProcessSP ValueObjectManager::GetProcessSP() const {
+  if (m_root_valobj_sp)
+    return m_root_valobj_sp->GetProcessSP();
+  return lldb::ProcessSP();
+}
+
+lldb::ThreadSP ValueObjectManager::GetThreadSP() const {
+  if (m_root_valobj_sp)
+    return m_root_valobj_sp->GetThreadSP();
+  return lldb::ThreadSP();
+}
+
+lldb::StackFrameSP ValueObjectManager::GetFrameSP() const {
+  if (m_root_valobj_sp)
+    return m_root_valobj_sp->GetFrameSP();
+  return lldb::StackFrameSP();
+}
+




More information about the lldb-commits mailing list