[Lldb-commits] [lldb] r152371 - in /lldb/trunk: examples/synthetic/gnu_libstdcpp.py include/lldb/Core/ValueObject.h source/Core/ValueObject.cpp source/Core/ValueObjectRegister.cpp
Enrico Granata
egranata at apple.com
Thu Mar 8 19:09:58 PST 2012
Author: enrico
Date: Thu Mar 8 21:09:58 2012
New Revision: 152371
URL: http://llvm.org/viewvc/llvm-project?rev=152371&view=rev
Log:
Changed ValueObject to use a dedicated ChildrenManager class to store its children, instead of an std::vector
This solves an issue where a ValueObject was getting a wrong children count (usually, a huge value) and trying to resize the vector of children to fit that many ValueObject*
Added a loop detection algorithm to the synthetic children provider for std::list
Added a few more checks to the synthetic children provider for std::vector
Both std::list and std::vector's synthetic children providers now cache the count of children instead of recomputing it every time
std::map has a field that stores the count, so there is little need to cache it on our side
Modified:
lldb/trunk/examples/synthetic/gnu_libstdcpp.py
lldb/trunk/include/lldb/Core/ValueObject.h
lldb/trunk/source/Core/ValueObject.cpp
lldb/trunk/source/Core/ValueObjectRegister.cpp
Modified: lldb/trunk/examples/synthetic/gnu_libstdcpp.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/gnu_libstdcpp.py?rev=152371&r1=152370&r2=152371&view=diff
==============================================================================
--- lldb/trunk/examples/synthetic/gnu_libstdcpp.py (original)
+++ lldb/trunk/examples/synthetic/gnu_libstdcpp.py Thu Mar 8 21:09:58 2012
@@ -12,7 +12,36 @@
self.valobj = valobj
self.update()
+ def next_node(self,node):
+ return node.GetChildMemberWithName('_M_next')
+
+ def is_valid(self,node):
+ return self.value(self.next_node(node)) != self.node_address
+
+ def value(self,node):
+ return node.GetValueAsUnsigned()
+
+ # Floyd's cyle-finding algorithm
+ # try to detect if this list has a loop
+ def has_loop(self):
+ slow = self.next
+ fast1 = self.next
+ fast2 = self.next
+ while self.is_valid(slow):
+ slow_value = self.value(slow)
+ fast1 = self.next_node(fast2)
+ fast2 = self.next_node(fast1)
+ if self.value(fast1) == slow_value or self.value(fast2) == slow_value:
+ return True
+ slow = self.next_node(slow)
+ return False
+
def num_children(self):
+ if self.count == None:
+ self.count = self.num_children_impl()
+ return self.count
+
+ def num_children_impl(self):
try:
next_val = self.next.GetValueAsUnsigned(0)
prev_val = self.prev.GetValueAsUnsigned(0)
@@ -23,6 +52,8 @@
return 0
if next_val == prev_val:
return 1
+ if self.has_loop():
+ return 0
size = 2
current = self.next
while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address:
@@ -70,6 +101,7 @@
self.prev = node.GetChildMemberWithName('_M_prev')
self.data_type = self.extract_type()
self.data_size = self.data_type.GetByteSize()
+ self.count = None
except:
pass
@@ -80,6 +112,16 @@
self.update()
def num_children(self):
+ if self.count == None:
+ self.count = self.num_children_impl()
+ return self.count
+
+ def is_valid_pointer(ptr,process):
+ error = lldb.SBError()
+ process.ReadMemory(ptr,1,error)
+ return False if error.Fail() else True
+
+ def num_children_impl(self):
try:
start_val = self.start.GetValueAsUnsigned(0)
finish_val = self.finish.GetValueAsUnsigned(0)
@@ -101,7 +143,14 @@
if finish_val > end_val:
return 0
- num_children = (finish_val-start_val)/self.data_size
+ # if we have a struct (or other data type that the compiler pads to native word size)
+ # this check might fail, unless the sizeof() we get is itself incremented to take the
+ # padding bytes into account - on current clang it looks like this is the case
+ num_children = (finish_val-start_val)
+ if (num_children % self.data_size) != 0:
+ return 0
+ else:
+ num_children = num_children/self.data_size
return num_children
except:
return 0;
@@ -131,6 +180,11 @@
self.end = impl.GetChildMemberWithName('_M_end_of_storage')
self.data_type = self.start.GetType().GetPointeeType()
self.data_size = self.data_type.GetByteSize()
+ # if any of these objects is invalid, it means there is no point in trying to fetch anything
+ if self.start.IsValid() and self.finish.IsValid() and self.end.IsValid() and self.data_type.IsValid():
+ self.count = None
+ else:
+ self.count = 0
except:
pass
Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=152371&r1=152370&r2=152371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Thu Mar 8 21:09:58 2012
@@ -993,6 +993,73 @@
protected:
typedef ClusterManager<ValueObject> ValueObjectManager;
+
+ class ChildrenManager
+ {
+ public:
+ ChildrenManager() :
+ m_mutex(Mutex::eMutexTypeRecursive),
+ m_children(),
+ m_children_count(0)
+ {}
+
+ bool
+ HasChildAtIndex (uint32_t idx)
+ {
+ Mutex::Locker(m_mutex);
+ ChildrenIterator iter = m_children.find(idx);
+ ChildrenIterator end = m_children.end();
+ return (iter != end);
+ }
+
+ ValueObject*
+ GetChildAtIndex (uint32_t idx)
+ {
+ Mutex::Locker(m_mutex);
+ ChildrenIterator iter = m_children.find(idx);
+ ChildrenIterator end = m_children.end();
+ if (iter == end)
+ return NULL;
+ else
+ return iter->second;
+ }
+
+ void
+ SetChildAtIndex (uint32_t idx, ValueObject* valobj)
+ {
+ ChildrenPair pair(idx,valobj); // we do not need to be mutex-protected to make a pair
+ Mutex::Locker(m_mutex);
+ m_children.insert(pair);
+ }
+
+ void
+ SetChildrenCount (uint32_t count)
+ {
+ m_children_count = count;
+ }
+
+ uint32_t
+ GetChildrenCount ()
+ {
+ return m_children_count;
+ }
+
+ void
+ Clear()
+ {
+ m_children_count = 0;
+ Mutex::Locker(m_mutex);
+ m_children.clear();
+ }
+
+ private:
+ typedef std::map<uint32_t, ValueObject*> ChildrenMap;
+ typedef ChildrenMap::iterator ChildrenIterator;
+ typedef ChildrenMap::value_type ChildrenPair;
+ Mutex m_mutex;
+ ChildrenMap m_children;
+ uint32_t m_children_count;
+ };
//------------------------------------------------------------------
// Classes that inherit from ValueObject can see and modify these
@@ -1020,7 +1087,7 @@
// as a shared pointer to any of them has been handed out. Shared pointers to
// value objects must always be made with the GetSP method.
- std::vector<ValueObject *> m_children;
+ ChildrenManager m_children;
std::map<ConstString, ValueObject *> m_synthetic_children;
ValueObject* m_dynamic_value;
Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=152371&r1=152370&r2=152371&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Thu Mar 8 21:09:58 2012
@@ -493,15 +493,16 @@
if (idx < GetNumChildren())
{
// Check if we have already made the child value object?
- if (can_create && m_children[idx] == NULL)
+ if (can_create && !m_children.HasChildAtIndex(idx))
{
// No we haven't created the child at this index, so lets have our
// subclass do it and cache the result for quick future access.
- m_children[idx] = CreateChildAtIndex (idx, false, 0);
+ m_children.SetChildAtIndex(idx,CreateChildAtIndex (idx, false, 0));
}
- if (m_children[idx] != NULL)
- return m_children[idx]->GetSP();
+ ValueObject* child = m_children.GetChildAtIndex(idx);
+ if (child != NULL)
+ return child->GetSP();
}
return child_sp;
}
@@ -568,13 +569,13 @@
{
SetNumChildren (CalculateNumChildren());
}
- return m_children.size();
+ return m_children.GetChildrenCount();
}
void
ValueObject::SetNumChildren (uint32_t num_children)
{
m_children_count_valid = true;
- m_children.resize(num_children);
+ m_children.SetChildrenCount(num_children);
}
void
Modified: lldb/trunk/source/Core/ValueObjectRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectRegister.cpp?rev=152371&r1=152370&r2=152371&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObjectRegister.cpp (original)
+++ lldb/trunk/source/Core/ValueObjectRegister.cpp Thu Mar 8 21:09:58 2012
@@ -204,7 +204,7 @@
{
SetValueIsValid (false);
m_error.SetErrorToGenericError ();
- m_children.clear();
+ m_children.Clear();
}
return m_error.Success();
}
More information about the lldb-commits
mailing list