Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 # Write out histogram information for C++. The histograms are defined
6 # in a file provided as a command-line argument.
8 from __future__ import with_statement
10 import sys
11 import histogram_tools
12 import itertools
14 banner = """/* This file is auto-generated, see gen-histogram-data.py. */
15 """
17 # Write out the gHistograms array.
19 class StringTable:
20 def __init__(self):
21 self.current_index = 0;
22 self.table = {}
24 def c_strlen(self, string):
25 return len(string) + 1
27 def stringIndex(self, string):
28 if string in self.table:
29 return self.table[string]
30 else:
31 result = self.current_index
32 self.table[string] = result
33 self.current_index += self.c_strlen(string)
34 return result
36 def writeDefinition(self, f, name):
37 entries = self.table.items()
38 entries.sort(key=lambda x:x[1])
39 # Avoid null-in-string warnings with GCC and potentially
40 # overlong string constants; write everything out the long way.
41 def explodeToCharArray(string):
42 def toCChar(s):
43 if s == "'":
44 return "'\\''"
45 else:
46 return "'%s'" % s
47 return ", ".join(map(toCChar, string))
48 f.write("const char %s[] = {\n" % name)
49 for (string, offset) in entries[:-1]:
50 e = explodeToCharArray(string)
51 if e:
52 f.write(" /* %5d */ %s, '\\0',\n"
53 % (offset, explodeToCharArray(string)))
54 else:
55 f.write(" /* %5d */ '\\0',\n" % offset)
56 f.write(" /* %5d */ %s, '\\0' };\n\n"
57 % (entries[-1][1], explodeToCharArray(entries[-1][0])))
59 def print_array_entry(histogram, name_index, exp_index):
60 cpp_guard = histogram.cpp_guard()
61 if cpp_guard:
62 print "#if defined(%s)" % cpp_guard
63 print " { %s, %s, %s, %s, %d, %d, %s }," \
64 % (histogram.low(), histogram.high(),
65 histogram.n_buckets(), histogram.nsITelemetry_kind(),
66 name_index, exp_index,
67 "true" if histogram.extended_statistics_ok() else "false")
68 if cpp_guard:
69 print "#endif"
71 def write_histogram_table(histograms):
72 table = StringTable()
74 print "const TelemetryHistogram gHistograms[] = {"
75 for histogram in histograms:
76 name_index = table.stringIndex(histogram.name())
77 exp_index = table.stringIndex(histogram.expiration())
78 print_array_entry(histogram, name_index, exp_index)
79 print "};"
81 strtab_name = "gHistogramStringTable"
82 table.writeDefinition(sys.stdout, strtab_name)
83 static_assert("sizeof(%s) <= UINT32_MAX" % strtab_name,
84 "index overflow")
86 # Write out static asserts for histogram data. We'd prefer to perform
87 # these checks in this script itself, but since several histograms
88 # (generally enumerated histograms) use compile-time constants for
89 # their upper bounds, we have to let the compiler do the checking.
91 def static_assert(expression, message):
92 print "static_assert(%s, \"%s\");" % (expression, message)
94 def static_asserts_for_boolean(histogram):
95 pass
97 def static_asserts_for_flag(histogram):
98 pass
100 def static_asserts_for_enumerated(histogram):
101 n_values = histogram.high()
102 static_assert("%s > 2" % n_values,
103 "Not enough values for %s" % histogram.name())
105 def shared_static_asserts(histogram):
106 name = histogram.name()
107 low = histogram.low()
108 high = histogram.high()
109 n_buckets = histogram.n_buckets()
110 static_assert("%s < %s" % (low, high), "low >= high for %s" % name)
111 static_assert("%s > 2" % n_buckets, "Not enough values for %s" % name)
112 static_assert("%s >= 1" % low, "Incorrect low value for %s" % name)
113 static_assert("%s > %s" % (high, n_buckets),
114 "high must be > number of buckets for %s; you may want an enumerated histogram" % name)
116 def static_asserts_for_linear(histogram):
117 shared_static_asserts(histogram)
119 def static_asserts_for_exponential(histogram):
120 shared_static_asserts(histogram)
122 def write_histogram_static_asserts(histograms):
123 print """
124 // Perform the checks at the beginning of HistogramGet at
125 // compile time, so that incorrect histogram definitions
126 // give compile-time errors, not runtime errors."""
128 table = {
129 'boolean' : static_asserts_for_boolean,
130 'flag' : static_asserts_for_flag,
131 'enumerated' : static_asserts_for_enumerated,
132 'linear' : static_asserts_for_linear,
133 'exponential' : static_asserts_for_exponential,
134 }
136 for histogram in histograms:
137 histogram_tools.table_dispatch(histogram.kind(), table,
138 lambda f: f(histogram))
140 def write_debug_histogram_ranges(histograms):
141 ranges_lengths = []
143 # Collect all the range information from individual histograms.
144 # Write that information out as well.
145 print "#ifdef DEBUG"
146 print "const int gBucketLowerBounds[] = {"
147 for histogram in histograms:
148 ranges = []
149 try:
150 ranges = histogram.ranges()
151 except histogram_tools.DefinitionException:
152 pass
153 ranges_lengths.append(len(ranges))
154 # Note that we do not test cpp_guard here. We do this so we
155 # will have complete information about all the histograms in
156 # this array. Just having information about the ranges of
157 # histograms is not platform-specific; if there are histograms
158 # that have platform-specific constants in their definitions,
159 # those histograms will fail in the .ranges() call above and
160 # we'll have a zero-length array to deal with here.
161 if len(ranges) > 0:
162 print ','.join(map(str, ranges)), ','
163 else:
164 print '/* Skipping %s */' % histogram.name()
165 print "};"
167 # Write the offsets into gBucketLowerBounds.
168 print "struct bounds { int offset; int length; };"
169 print "const struct bounds gBucketLowerBoundIndex[] = {"
170 offset = 0
171 for (histogram, range_length) in itertools.izip(histograms, ranges_lengths):
172 cpp_guard = histogram.cpp_guard()
173 # We do test cpp_guard here, so that histogram IDs are valid
174 # indexes into this array.
175 if cpp_guard:
176 print "#if defined(%s)" % cpp_guard
177 print "{ %d, %d }," % (offset, range_length)
178 if cpp_guard:
179 print "#endif"
180 offset += range_length
181 print "};"
182 print "#endif"
184 def main(argv):
185 filename = argv[0]
187 histograms = list(histogram_tools.from_file(filename))
189 print banner
190 write_histogram_table(histograms)
191 write_histogram_static_asserts(histograms)
192 write_debug_histogram_ranges(histograms)
194 main(sys.argv[1:])