blob: da7ba456a258bd40ad7729ffa1ae072ad09856ae [file] [log] [blame]
Enrico Granatad589b342013-09-04 17:48:52 +00001import lldb
2
3_map_capping_size = 255
4
Kate Stoneb9c1b512016-09-06 20:57:50 +00005
Enrico Granatad589b342013-09-04 17:48:52 +00006class libcxx_hash_table_SynthProvider:
Enrico Granatad589b342013-09-04 17:48:52 +00007
Kate Stoneb9c1b512016-09-06 20:57:50 +00008 def __init__(self, valobj, dict):
9 self.valobj = valobj
10 self.num_elements = None
11 self.next_element = None
12 self.bucket_count = None
Enrico Granatad589b342013-09-04 17:48:52 +000013
Kate Stoneb9c1b512016-09-06 20:57:50 +000014 def update(self):
15 logger = lldb.formatters.Logger.Logger()
16 self.num_elements = None
17 self.next_element = None
18 self.bucket_count = None
19 try:
20 # unordered_map is made up of a hash_map, which has 4 pieces in it:
21 # bucket list :
22 # array of buckets
23 # p1 (pair):
24 # first - pointer to first loaded element
25 # p2 (pair):
26 # first - number of elements
27 # second - hash function
28 # p3 (pair):
29 # first - max_load_factor
30 # second - equality operator function
31 #
32 # For display, we actually don't need to go inside the buckets, since 'p1' has a way to iterate over all
33 # the elements directly.
34 #
35 # We will calculate other values about the map because they will be useful for the summary.
36 #
37 table = self.valobj.GetChildMemberWithName('__table_')
Enrico Granatad589b342013-09-04 17:48:52 +000038
Kate Stoneb9c1b512016-09-06 20:57:50 +000039 bl_ptr = table.GetChildMemberWithName(
40 '__bucket_list_').GetChildMemberWithName('__ptr_')
41 self.bucket_array_ptr = bl_ptr.GetChildMemberWithName(
42 '__first_').GetValueAsUnsigned(0)
43 self.bucket_count = bl_ptr.GetChildMemberWithName('__second_').GetChildMemberWithName(
44 '__data_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
45 logger >> "Bucket count = %r" % self.bucket_count
Enrico Granatad589b342013-09-04 17:48:52 +000046
Kate Stoneb9c1b512016-09-06 20:57:50 +000047 self.begin_ptr = table.GetChildMemberWithName('__p1_').GetChildMemberWithName(
48 '__first_').GetChildMemberWithName('__next_')
Enrico Granatad589b342013-09-04 17:48:52 +000049
Kate Stoneb9c1b512016-09-06 20:57:50 +000050 self.num_elements = table.GetChildMemberWithName(
51 '__p2_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
52 self.max_load_factor = table.GetChildMemberWithName(
53 '__p3_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
54 logger >> "Num elements = %r" % self.num_elements
Enrico Granatad589b342013-09-04 17:48:52 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 # save the pointers as we get them
57 # -- don't access this first element if num_element==0!
58 self.elements_cache = []
59 if self.num_elements:
60 self.next_element = self.begin_ptr
61 else:
62 self.next_element = None
63 except Exception as e:
64 logger >> "Caught exception: %r" % e
65 pass
Enrico Granatad589b342013-09-04 17:48:52 +000066
Kate Stoneb9c1b512016-09-06 20:57:50 +000067 def num_children(self):
68 global _map_capping_size
69 num_elements = self.num_elements
70 if num_elements is not None:
71 if num_elements > _map_capping_size:
72 num_elements = _map_capping_size
73 return num_elements
Enrico Granatad589b342013-09-04 17:48:52 +000074
Kate Stoneb9c1b512016-09-06 20:57:50 +000075 def has_children(self):
76 return True
Enrico Granatad589b342013-09-04 17:48:52 +000077
Kate Stoneb9c1b512016-09-06 20:57:50 +000078 def get_child_index(self, name):
79 logger = lldb.formatters.Logger.Logger()
80 try:
81 return int(name.lstrip('[').rstrip(']'))
82 except:
83 return -1
Enrico Granatad589b342013-09-04 17:48:52 +000084
Kate Stoneb9c1b512016-09-06 20:57:50 +000085 def get_child_at_index(self, index):
86 logger = lldb.formatters.Logger.Logger()
87 logger >> "Retrieving child " + str(index)
88 if index < 0:
89 return None
90 if index >= self.num_children():
91 return None
Enrico Granatad589b342013-09-04 17:48:52 +000092
Kate Stoneb9c1b512016-09-06 20:57:50 +000093 # extend
94 logger >> " : cache size starts with %d elements" % len(
95 self.elements_cache)
96 while index >= len(self.elements_cache):
97 # if we hit the end before we get the index, give up:
98 if not self.next_element:
99 logger >> " : hit end of list"
100 return None
Enrico Granatad589b342013-09-04 17:48:52 +0000101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 node = self.next_element.Dereference()
Enrico Granatad589b342013-09-04 17:48:52 +0000103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 value = node.GetChildMemberWithName('__value_')
105 hash_value = node.GetChildMemberWithName(
106 '__hash_').GetValueAsUnsigned()
107 self.elements_cache.append((value, hash_value))
Enrico Granatad589b342013-09-04 17:48:52 +0000108
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 self.next_element = node.GetChildMemberWithName('__next_')
110 if not self.next_element.GetValueAsUnsigned(0):
111 self.next_element = None
112
113 # hit the index! so we have the value
114 logger >> " : cache size ends with %d elements" % len(
115 self.elements_cache)
116 value, hash_value = self.elements_cache[index]
117 return self.valobj.CreateValueFromData(
118 '[%d] <hash %d>' %
119 (index, hash_value), value.GetData(), value.GetType())
Enrico Granatad589b342013-09-04 17:48:52 +0000120
121
Kate Stoneb9c1b512016-09-06 20:57:50 +0000122def __lldb_init_module(debugger, dict):
123 debugger.HandleCommand(
124 'type synthetic add -l unordered_multi.libcxx_hash_table_SynthProvider -x "^(std::__1::)unordered_(multi)?(map|set)<.+> >$" -w libcxx')