[Lldb-commits] [lldb] r189964 - This is an example synthetic provider for libc++ unordered (multi) maps&set

Enrico Granata egranata at apple.com
Wed Sep 4 10:48:53 PDT 2013


Author: enrico
Date: Wed Sep  4 12:48:52 2013
New Revision: 189964

URL: http://llvm.org/viewvc/llvm-project?rev=189964&view=rev
Log:
This is an example synthetic provider for libc++ unordered (multi) maps&set
Thanks to Jared Grubb for writing it and sharing it!


Added:
    lldb/trunk/examples/synthetic/unordered_multi.py

Added: lldb/trunk/examples/synthetic/unordered_multi.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/unordered_multi.py?rev=189964&view=auto
==============================================================================
--- lldb/trunk/examples/synthetic/unordered_multi.py (added)
+++ lldb/trunk/examples/synthetic/unordered_multi.py Wed Sep  4 12:48:52 2013
@@ -0,0 +1,110 @@
+import lldb
+
+_map_capping_size = 255
+
+class libcxx_hash_table_SynthProvider:
+	def __init__(self, valobj, dict):
+		self.valobj = valobj
+		self.num_elements = None
+		self.next_element = None
+		self.bucket_count = None
+
+	def update(self):
+		logger = lldb.formatters.Logger.Logger()
+		self.num_elements = None
+		self.next_element = None
+		self.bucket_count = None
+		try:
+			# unordered_map is made up a a hash_map, which has 4 pieces in it:
+			#   bucket list :
+			#      array of buckets
+			#   p1 (pair):
+			#      first - pointer to first loaded element
+			#   p2 (pair):
+			#      first - number of elements
+			#      second - hash function
+			#   p3 (pair):
+			#      first - max_load_factor
+			#      second - equality operator function
+			#
+			# For display, we actually dont need to go inside the buckets, since 'p1' has a way to iterate over all
+			# the elements directly.
+			#
+			# We will calculate other values about the map because they will be useful for the summary.
+			#
+			table = self.valobj.GetChildMemberWithName('__table_')
+
+			bl_ptr = table.GetChildMemberWithName('__bucket_list_').GetChildMemberWithName('__ptr_')
+			self.bucket_array_ptr = bl_ptr.GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
+			self.bucket_count = bl_ptr.GetChildMemberWithName('__second_').GetChildMemberWithName('__data_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
+			logger >> "Bucket count = %r" % self.bucket_count
+
+			self.begin_ptr = table.GetChildMemberWithName('__p1_').GetChildMemberWithName('__first_').GetChildMemberWithName('__next_')
+
+			self.num_elements    = table.GetChildMemberWithName('__p2_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
+			self.max_load_factor = table.GetChildMemberWithName('__p3_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
+			logger >> "Num elements = %r" % self.num_elements
+
+			# save the pointers as we get them
+			#   -- dont access this first element if num_element==0!
+			self.elements_cache = []
+			if self.num_elements:
+				self.next_element = self.begin_ptr
+			else:
+				self.next_element = None
+		except Exception, e:
+			logger >> "Caught exception: %r" % e
+			pass
+
+	def num_children(self):
+		global _map_capping_size
+		num_elements = self.num_elements
+		if num_elements is not None:
+			if num_elements > _map_capping_size:
+				num_elements = _map_capping_size
+		return num_elements
+
+	def has_children(self):
+		return True
+
+	def get_child_index(self,name):
+		logger = lldb.formatters.Logger.Logger()
+		try:
+			return int(name.lstrip('[').rstrip(']'))
+		except:
+			return -1
+
+	def get_child_at_index(self,index):
+		logger = lldb.formatters.Logger.Logger()
+		logger >> "Retrieving child " + str(index)
+		if index < 0:
+			return None
+		if index >= self.num_children():
+			return None
+
+		# extend
+		logger >> " : cache size starts with %d elements" % len(self.elements_cache)
+		while index >= len(self.elements_cache):
+			# if we hit the end before we get the index, give up:
+			if not self.next_element:
+				logger >> " : hit end of list"
+				return None
+
+			node = self.next_element.Dereference()
+
+			value = node.GetChildMemberWithName('__value_')
+			hash_value = node.GetChildMemberWithName('__hash_').GetValueAsUnsigned()
+			self.elements_cache.append((value, hash_value))
+
+			self.next_element = node.GetChildMemberWithName('__next_')
+			if not self.next_element.GetValueAsUnsigned(0):
+				self.next_element = None
+
+		# hit the index! so we have the value
+		logger >> " : cache size ends with %d elements" % len(self.elements_cache)
+		value, hash_value = self.elements_cache[index]
+		return self.valobj.CreateValueFromData('[%d] <hash %d>'%(index,hash_value), value.GetData(), value.GetType())
+
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand('type synthetic add -l unordered_multi.libcxx_hash_table_SynthProvider -x "^(std::__1::)unordered_(multi)?(map|set)<.+> >$" -w libcxx')





More information about the lldb-commits mailing list