forked from OSchip/llvm-project
125 lines
4.7 KiB
Python
125 lines
4.7 KiB
Python
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 of 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 don't 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
|
|
# -- don't 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 as 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')
|