1 : // Copyright 2012 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 BasicBlockEntryCountGrinder class, which processes trace files
16 : // containing basic-block frequency data and outputs a summary JSON file.
17 :
18 : #ifndef SYZYGY_GRINDER_GRINDERS_BASIC_BLOCK_ENTRY_COUNT_GRINDER_H_
19 : #define SYZYGY_GRINDER_GRINDERS_BASIC_BLOCK_ENTRY_COUNT_GRINDER_H_
20 :
21 : #include <map>
22 : #include <vector>
23 :
24 : #include "base/values.h"
25 : #include "syzygy/grinder/basic_block_entry_count_serializer.h"
26 : #include "syzygy/grinder/basic_block_util.h"
27 : #include "syzygy/grinder/grinder.h"
28 :
29 : namespace grinder {
30 : namespace grinders {
31 :
32 : // This class processes trace files containing basic-block frequency data,
33 : // populating an EntryCountMap with summary entry counts, and
34 : // generating a JSON output file.
35 : //
36 : // See basic_block_entry_count_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 BasicBlockEntryCountGrinder : public GrinderInterface {
41 : public:
42 : BasicBlockEntryCountGrinder();
43 :
44 : // @name GrinderInterface implementation.
45 : // @{
46 : virtual bool ParseCommandLine(const CommandLine* command_line) OVERRIDE;
47 : virtual void SetParser(Parser* parser) OVERRIDE;
48 : virtual bool Grind() OVERRIDE;
49 : virtual bool OutputData(FILE* file) OVERRIDE;
50 : // @}
51 :
52 : // @name ParseEventHandler overrides.
53 : // @{
54 : // Override of the OnIndexedFrequency callback.
55 : // NOTE: This only process TraceIndexedFrequencyData records of the
56 : // appropriate type (basic-block entry counts).
57 : virtual void OnIndexedFrequency(
58 : base::Time time,
59 : DWORD process_id,
60 : DWORD thread_id,
61 : const TraceIndexedFrequencyData* data) OVERRIDE;
62 : // @}
63 :
64 : // @returns a map from ModuleInformation records to bb entry counts.
65 E : const basic_block_util::ModuleEntryCountMap& entry_count_map() const {
66 E : return entry_count_map_;
67 E : }
68 :
69 : protected:
70 : typedef basic_block_util::RelativeAddressRangeVector
71 : RelativeAddressRangeVector;
72 : typedef basic_block_util::ModuleInformation ModuleInformation;
73 : typedef basic_block_util::ModuleIdentityComparator ModuleIdentityComparator;
74 :
75 : // The data we store per encountered instrumented module.
76 : struct InstrumentedModuleInformation {
77 : // The basic block ranges allow us to resolve the ordinal basic block
78 : // IDs to relative offsets in the original image.
79 : RelativeAddressRangeVector block_ranges;
80 :
81 : // The module information for the original image is what goes into the
82 : // ModuleEntryCount map.
83 : ModuleInformation original_module;
84 : };
85 :
86 : typedef std::map<ModuleInformation,
87 : InstrumentedModuleInformation,
88 : ModuleIdentityComparator> InstrumentedModuleMap;
89 :
90 : // This method does the actual updating of the entry counts on receipt
91 : // of basic-block frequency data. It is implemented separately from the
92 : // main hook for unit-testing purposes.
93 : // @param module_info the module whose basic-block entries are being counted.
94 : // @param data the basic-block entry counts being reported. The data type of
95 : // this record is expected to be a basic-blocks entry counts.
96 : void UpdateBasicBlockEntryCount(
97 : const InstrumentedModuleInformation& module_info,
98 : const TraceIndexedFrequencyData* data);
99 :
100 : // Finds or creates a new entry for an encountered instrumented module.
101 : // @param module_info the module info for the instrumented module encountered.
102 : // @returns the initialized instrumented module on success, or NULL on failure
103 : // to locate the instrumented module or initialize the module information.
104 : const InstrumentedModuleInformation* FindOrCreateInstrumentedModule(
105 : const ModuleInformation* module_info);
106 :
107 : // Stores the summarized basic-block entry counts for each module encountered.
108 : basic_block_util::ModuleEntryCountMap entry_count_map_;
109 :
110 : // Stores the basic block ID maps for each module encountered.
111 : InstrumentedModuleMap instrumented_modules_;
112 :
113 : // Used to save the JSON output to a file. Also tracks the pretty-printing
114 : // status of this grinder.
115 : BasicBlockEntryCountSerializer serializer_;
116 :
117 : // Points to the parser that is feeding us events. Used to get module
118 : // information.
119 : Parser* parser_;
120 :
121 : // Set to true if any call to OnIndexedFrequency fails. Processing will
122 : // continue with a warning that results may be partial.
123 : bool event_handler_errored_;
124 :
125 : private:
126 : DISALLOW_COPY_AND_ASSIGN(BasicBlockEntryCountGrinder);
127 : };
128 :
129 : } // namespace grinders
130 : } // namespace grinder
131 :
132 : #endif // SYZYGY_GRINDER_GRINDERS_BASIC_BLOCK_ENTRY_COUNT_GRINDER_H_
|