1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares the IndexedFrequencyDataGrinder class, which processes trace files
16 : // containing indexed frequencies data and outputs a summary JSON file.
17 :
18 : #ifndef SYZYGY_GRINDER_GRINDERS_INDEXED_FREQUENCY_DATA_GRINDER_H_
19 : #define SYZYGY_GRINDER_GRINDERS_INDEXED_FREQUENCY_DATA_GRINDER_H_
20 :
21 : #include <map>
22 : #include <vector>
23 :
24 : #include "base/values.h"
25 : #include "syzygy/grinder/basic_block_util.h"
26 : #include "syzygy/grinder/grinder.h"
27 : #include "syzygy/grinder/indexed_frequency_data_serializer.h"
28 :
29 : namespace grinder {
30 : namespace grinders {
31 :
32 : // This class processes trace files containing branch frequency data, populating
33 : // an IndexedFrequencyMap with summary frequencies, and generating a JSON
34 : // output file.
35 : //
36 : // See indexed_frequency_data_serializer.h for the resulting JSON structure.
37 : //
38 : // The JSON output will be pretty printed if --pretty-print is included in the
39 : // command line passed to ParseCommandLine().
40 : class IndexedFrequencyDataGrinder : public GrinderInterface {
41 : public:
42 : typedef basic_block_util::ModuleIndexedFrequencyMap ModuleIndexedFrequencyMap;
43 :
44 : IndexedFrequencyDataGrinder();
45 :
46 : // @name GrinderInterface implementation.
47 : // @{
48 : virtual bool ParseCommandLine(const base::CommandLine* command_line) override;
49 : virtual void SetParser(Parser* parser) override;
50 : virtual bool Grind() override;
51 : virtual bool OutputData(FILE* file) override;
52 : // @}
53 :
54 : // @name ParseEventHandler overrides.
55 : // @{
56 : // Override of the OnIndexedFrequency callback.
57 : // NOTE: This only process TraceIndexedFrequencyData records of the
58 : // appropriate type (bbentry, branch and coverage).
59 : virtual void OnIndexedFrequency(
60 : base::Time time,
61 : DWORD process_id,
62 : DWORD thread_id,
63 : const TraceIndexedFrequencyData* data) override;
64 : // @}
65 :
66 : // @returns a map from ModuleInformation records to basic block frequencies.
67 E : const ModuleIndexedFrequencyMap& frequency_data_map() const {
68 E : return frequency_data_map_;
69 E : }
70 :
71 : protected:
72 : typedef basic_block_util::RelativeAddressRangeVector
73 : RelativeAddressRangeVector;
74 : typedef basic_block_util::ModuleInformation ModuleInformation;
75 : typedef basic_block_util::ModuleIdentityComparator ModuleIdentityComparator;
76 :
77 : // The data we store per encountered instrumented module.
78 : struct InstrumentedModuleInformation {
79 : // The basic block ranges allow us to resolve the ordinal basic block
80 : // IDs to relative offsets in the original image.
81 : RelativeAddressRangeVector block_ranges;
82 :
83 : // The module information for the original image is what goes into the
84 : // IndexedFrequencyMap map.
85 : ModuleInformation original_module;
86 : };
87 :
88 : typedef std::map<ModuleInformation,
89 : InstrumentedModuleInformation,
90 : ModuleIdentityComparator> InstrumentedModuleMap;
91 :
92 : // This method does the actual updating of the frequencies on receipt
93 : // of basic-block frequency data. It is implemented separately from the
94 : // main hook for unit-testing purposes.
95 : // @param module_info the module whose basic-block frequencies are being
96 : // counted.
97 : // @param data the basic-block frequencies being reported. The data type of
98 : // this record is expected to be a basic-blocks data frequencies.
99 : void UpdateBasicBlockFrequencyData(
100 : const InstrumentedModuleInformation& module_info,
101 : const TraceIndexedFrequencyData* data);
102 :
103 : // Finds or creates a new entry for an encountered instrumented module.
104 : // @param module_info the module info for the instrumented module encountered.
105 : // @returns the initialized instrumented module on success, or NULL on failure
106 : // to locate the instrumented module or initialize the module information.
107 : const InstrumentedModuleInformation* FindOrCreateInstrumentedModule(
108 : const ModuleInformation* module_info);
109 :
110 : // Stores the summarized basic-block frequencies for each module encountered.
111 : ModuleIndexedFrequencyMap frequency_data_map_;
112 :
113 : // Stores the basic block ID maps for each module encountered.
114 : InstrumentedModuleMap instrumented_modules_;
115 :
116 : // Used to save the JSON output to a file. Also tracks the pretty-printing
117 : // status of this grinder.
118 : IndexedFrequencyDataSerializer serializer_;
119 :
120 : // Points to the parser that is feeding us events. Used to get module
121 : // information.
122 : Parser* parser_;
123 :
124 : // Set to true if any call to OnIndexedFrequency fails. Processing will
125 : // continue with a warning that results may be partial.
126 : bool event_handler_errored_;
127 :
128 : private:
129 : DISALLOW_COPY_AND_ASSIGN(IndexedFrequencyDataGrinder);
130 : };
131 :
132 : } // namespace grinders
133 : } // namespace grinder
134 :
135 : #endif // SYZYGY_GRINDER_GRINDERS_INDEXED_FREQUENCY_DATA_GRINDER_H_
|