blob: a5cb981b4fc9534885e5ffd89678be350b78815c [file] [log] [blame]
Enrico Granatad589b342013-09-04 17:48:52 +00001import lldb
2
3_map_capping_size = 255
4
5class libcxx_hash_table_SynthProvider:
6 def __init__(self, valobj, dict):
7 self.valobj = valobj
8 self.num_elements = None
9 self.next_element = None
10 self.bucket_count = None
11
12 def update(self):
13 logger = lldb.formatters.Logger.Logger()
14 self.num_elements = None
15 self.next_element = None
16 self.bucket_count = None
17 try:
18 # unordered_map is made up a a hash_map, which has 4 pieces in it:
19 # bucket list :
20 # array of buckets
21 # p1 (pair):
22 # first - pointer to first loaded element
23 # p2 (pair):
24 # first - number of elements
25 # second - hash function
26 # p3 (pair):
27 # first - max_load_factor
28 # second - equality operator function
29 #
30 # For display, we actually dont need to go inside the buckets, since 'p1' has a way to iterate over all
31 # the elements directly.
32 #
33 # We will calculate other values about the map because they will be useful for the summary.
34 #
35 table = self.valobj.GetChildMemberWithName('__table_')
36
37 bl_ptr = table.GetChildMemberWithName('__bucket_list_').GetChildMemberWithName('__ptr_')
38 self.bucket_array_ptr = bl_ptr.GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
39 self.bucket_count = bl_ptr.GetChildMemberWithName('__second_').GetChildMemberWithName('__data_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
40 logger >> "Bucket count = %r" % self.bucket_count
41
42 self.begin_ptr = table.GetChildMemberWithName('__p1_').GetChildMemberWithName('__first_').GetChildMemberWithName('__next_')
43
44 self.num_elements = table.GetChildMemberWithName('__p2_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
45 self.max_load_factor = table.GetChildMemberWithName('__p3_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
46 logger >> "Num elements = %r" % self.num_elements
47
48 # save the pointers as we get them
49 # -- dont access this first element if num_element==0!
50 self.elements_cache = []
51 if self.num_elements:
52 self.next_element = self.begin_ptr
53 else:
54 self.next_element = None
55 except Exception, e:
56 logger >> "Caught exception: %r" % e
57 pass
58
59 def num_children(self):
60 global _map_capping_size
61 num_elements = self.num_elements
62 if num_elements is not None:
63 if num_elements > _map_capping_size:
64 num_elements = _map_capping_size
65 return num_elements
66
67 def has_children(self):
68 return True
69
70 def get_child_index(self,name):
71 logger = lldb.formatters.Logger.Logger()
72 try:
73 return int(name.lstrip('[').rstrip(']'))
74 except:
75 return -1
76
77 def get_child_at_index(self,index):
78 logger = lldb.formatters.Logger.Logger()
79 logger >> "Retrieving child " + str(index)
80 if index < 0:
81 return None
82 if index >= self.num_children():
83 return None
84
85 # extend
86 logger >> " : cache size starts with %d elements" % len(self.elements_cache)
87 while index >= len(self.elements_cache):
88 # if we hit the end before we get the index, give up:
89 if not self.next_element:
90 logger >> " : hit end of list"
91 return None
92
93 node = self.next_element.Dereference()
94
95 value = node.GetChildMemberWithName('__value_')
96 hash_value = node.GetChildMemberWithName('__hash_').GetValueAsUnsigned()
97 self.elements_cache.append((value, hash_value))
98
99 self.next_element = node.GetChildMemberWithName('__next_')
100 if not self.next_element.GetValueAsUnsigned(0):
101 self.next_element = None
102
103 # hit the index! so we have the value
104 logger >> " : cache size ends with %d elements" % len(self.elements_cache)
105 value, hash_value = self.elements_cache[index]
106 return self.valobj.CreateValueFromData('[%d] <hash %d>'%(index,hash_value), value.GetData(), value.GetType())
107
108
109def __lldb_init_module(debugger,dict):
110 debugger.HandleCommand('type synthetic add -l unordered_multi.libcxx_hash_table_SynthProvider -x "^(std::__1::)unordered_(multi)?(map|set)<.+> >$" -w libcxx')