OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/compiler_stats.h" | 5 #include "vm/compiler_stats.h" |
6 | 6 |
7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
8 #include "vm/log.h" | 8 #include "vm/log.h" |
9 #include "vm/object_graph.h" | 9 #include "vm/object_graph.h" |
10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
11 #include "vm/timer.h" | 11 #include "vm/timer.h" |
12 | 12 |
13 | |
14 namespace dart { | 13 namespace dart { |
15 | 14 |
16 DEFINE_FLAG(bool, compiler_stats, false, "Compiler stat counters."); | 15 DEFINE_FLAG(bool, compiler_stats, false, "Compiler stat counters."); |
17 DEFINE_FLAG(bool, | 16 DEFINE_FLAG(bool, |
18 compiler_benchmark, | 17 compiler_benchmark, |
19 false, | 18 false, |
20 "Compiler stat counters for benchmark."); | 19 "Compiler stat counters for benchmark."); |
21 | 20 |
22 | |
23 class TokenStreamVisitor : public ObjectVisitor { | 21 class TokenStreamVisitor : public ObjectVisitor { |
24 public: | 22 public: |
25 explicit TokenStreamVisitor(CompilerStats* compiler_stats) | 23 explicit TokenStreamVisitor(CompilerStats* compiler_stats) |
26 : obj_(Object::Handle()), stats_(compiler_stats) {} | 24 : obj_(Object::Handle()), stats_(compiler_stats) {} |
27 | 25 |
28 void VisitObject(RawObject* raw_obj) { | 26 void VisitObject(RawObject* raw_obj) { |
29 if (raw_obj->IsPseudoObject()) { | 27 if (raw_obj->IsPseudoObject()) { |
30 return; // Cannot be wrapped in handles. | 28 return; // Cannot be wrapped in handles. |
31 } | 29 } |
32 obj_ = raw_obj; | 30 obj_ = raw_obj; |
33 if (obj_.GetClassId() == TokenStream::kClassId) { | 31 if (obj_.GetClassId() == TokenStream::kClassId) { |
34 TokenStream::Iterator tkit( | 32 TokenStream::Iterator tkit( |
35 Thread::Current()->zone(), TokenStream::Cast(obj_), | 33 Thread::Current()->zone(), TokenStream::Cast(obj_), |
36 TokenPosition::kMinSource, TokenStream::Iterator::kNoNewlines); | 34 TokenPosition::kMinSource, TokenStream::Iterator::kNoNewlines); |
37 Token::Kind kind = tkit.CurrentTokenKind(); | 35 Token::Kind kind = tkit.CurrentTokenKind(); |
38 while (kind != Token::kEOS) { | 36 while (kind != Token::kEOS) { |
39 ++stats_->num_tokens_total; | 37 ++stats_->num_tokens_total; |
40 tkit.Advance(); | 38 tkit.Advance(); |
41 kind = tkit.CurrentTokenKind(); | 39 kind = tkit.CurrentTokenKind(); |
42 } | 40 } |
43 } | 41 } |
44 } | 42 } |
45 | 43 |
46 private: | 44 private: |
47 Object& obj_; | 45 Object& obj_; |
48 CompilerStats* stats_; | 46 CompilerStats* stats_; |
49 }; | 47 }; |
50 | 48 |
51 | |
52 CompilerStats::CompilerStats(Isolate* isolate) | 49 CompilerStats::CompilerStats(Isolate* isolate) |
53 : isolate_(isolate), | 50 : isolate_(isolate), |
54 #define INITIALIZE_TIMER(timer_name, description) timer_name(true, description), | 51 #define INITIALIZE_TIMER(timer_name, description) timer_name(true, description), |
55 STAT_TIMERS(INITIALIZE_TIMER) | 52 STAT_TIMERS(INITIALIZE_TIMER) |
56 #undef INITIALIZE_TIMER | 53 #undef INITIALIZE_TIMER |
57 | 54 |
58 #define INITIALIZE_COUNTERS(counter_name) counter_name(0), | 55 #define INITIALIZE_COUNTERS(counter_name) counter_name(0), |
59 STAT_COUNTERS(INITIALIZE_COUNTERS) | 56 STAT_COUNTERS(INITIALIZE_COUNTERS) |
60 #undef INITIALIZE_COUNTERS | 57 #undef INITIALIZE_COUNTERS |
61 text(NULL), | 58 text(NULL), |
62 use_benchmark_output(false) { | 59 use_benchmark_output(false) { |
63 } | 60 } |
64 | 61 |
65 | |
66 #ifndef PRODUCT | 62 #ifndef PRODUCT |
67 | 63 |
68 | |
69 // Used to aggregate stats. Must be atomic. | 64 // Used to aggregate stats. Must be atomic. |
70 void CompilerStats::Add(const CompilerStats& other) { | 65 void CompilerStats::Add(const CompilerStats& other) { |
71 #define ADD_TOTAL(timer_name, literal) timer_name.AddTotal(other.timer_name); | 66 #define ADD_TOTAL(timer_name, literal) timer_name.AddTotal(other.timer_name); |
72 | 67 |
73 STAT_TIMERS(ADD_TOTAL) | 68 STAT_TIMERS(ADD_TOTAL) |
74 #undef ADD_TOTAL | 69 #undef ADD_TOTAL |
75 | 70 |
76 #define ADD_COUNTER(counter_name) \ | 71 #define ADD_COUNTER(counter_name) \ |
77 AtomicOperations::IncrementInt64By(&counter_name, other.counter_name); | 72 AtomicOperations::IncrementInt64By(&counter_name, other.counter_name); |
78 | 73 |
79 STAT_COUNTERS(ADD_COUNTER) | 74 STAT_COUNTERS(ADD_COUNTER) |
80 #undef ADD_COUNTER | 75 #undef ADD_COUNTER |
81 } | 76 } |
82 | 77 |
83 | |
84 void CompilerStats::Clear() { | 78 void CompilerStats::Clear() { |
85 #define CLEAR_TIMER(timer_name, literal) timer_name.Reset(); | 79 #define CLEAR_TIMER(timer_name, literal) timer_name.Reset(); |
86 | 80 |
87 STAT_TIMERS(CLEAR_TIMER) | 81 STAT_TIMERS(CLEAR_TIMER) |
88 #undef CLEAR_TIMER | 82 #undef CLEAR_TIMER |
89 | 83 |
90 #define CLEAR_COUNTER(counter_name) counter_name = 0; | 84 #define CLEAR_COUNTER(counter_name) counter_name = 0; |
91 | 85 |
92 STAT_COUNTERS(CLEAR_COUNTER) | 86 STAT_COUNTERS(CLEAR_COUNTER) |
93 #undef CLEAR_COUNTER | 87 #undef CLEAR_COUNTER |
94 } | 88 } |
95 | 89 |
96 | |
97 bool CompilerStats::IsCleared() const { | 90 bool CompilerStats::IsCleared() const { |
98 #define CHECK_TIMERS(timer_name, literal) \ | 91 #define CHECK_TIMERS(timer_name, literal) \ |
99 if (!timer_name.IsReset()) return false; | 92 if (!timer_name.IsReset()) return false; |
100 | 93 |
101 STAT_TIMERS(CHECK_TIMERS) | 94 STAT_TIMERS(CHECK_TIMERS) |
102 #undef CHECK_TIMERS | 95 #undef CHECK_TIMERS |
103 | 96 |
104 #define CHECK_COUNTERS(counter_name) \ | 97 #define CHECK_COUNTERS(counter_name) \ |
105 if (counter_name != 0) return false; | 98 if (counter_name != 0) return false; |
106 | 99 |
107 STAT_COUNTERS(CHECK_COUNTERS) | 100 STAT_COUNTERS(CHECK_COUNTERS) |
108 #undef CHECK_COUNTERS | 101 #undef CHECK_COUNTERS |
109 return true; | 102 return true; |
110 } | 103 } |
111 | 104 |
112 | |
113 // This function is used as a callback in the log object to which the | 105 // This function is used as a callback in the log object to which the |
114 // compiler stats are printed. It will be called only once, to print | 106 // compiler stats are printed. It will be called only once, to print |
115 // the accumulated text when all of the compiler stats values are | 107 // the accumulated text when all of the compiler stats values are |
116 // added to the log. | 108 // added to the log. |
117 static void PrintToStats(const char* format, ...) PRINTF_ATTRIBUTE(1, 2); | 109 static void PrintToStats(const char* format, ...) PRINTF_ATTRIBUTE(1, 2); |
118 static void PrintToStats(const char* format, ...) { | 110 static void PrintToStats(const char* format, ...) { |
119 Thread* thread = Thread::Current(); | 111 Thread* thread = Thread::Current(); |
120 Isolate* isolate = thread->isolate(); | 112 Isolate* isolate = thread->isolate(); |
121 CompilerStats* stats = isolate->aggregate_compiler_stats(); | 113 CompilerStats* stats = isolate->aggregate_compiler_stats(); |
122 Zone* zone = thread->zone(); | 114 Zone* zone = thread->zone(); |
123 ASSERT(stats != NULL); | 115 ASSERT(stats != NULL); |
124 va_list args; | 116 va_list args; |
125 va_start(args, format); | 117 va_start(args, format); |
126 stats->text = zone->VPrint(format, args); | 118 stats->text = zone->VPrint(format, args); |
127 va_end(args); | 119 va_end(args); |
128 } | 120 } |
129 | 121 |
130 | |
131 void CompilerStats::Update() { | 122 void CompilerStats::Update() { |
132 // Traverse the heap and compute number of tokens in all | 123 // Traverse the heap and compute number of tokens in all |
133 // TokenStream objects. | 124 // TokenStream objects. |
134 num_tokens_total = 0; | 125 num_tokens_total = 0; |
135 TokenStreamVisitor visitor(this); | 126 TokenStreamVisitor visitor(this); |
136 isolate_->heap()->IterateObjects(&visitor); | 127 isolate_->heap()->IterateObjects(&visitor); |
137 Dart::vm_isolate()->heap()->IterateObjects(&visitor); | 128 Dart::vm_isolate()->heap()->IterateObjects(&visitor); |
138 } | 129 } |
139 | 130 |
140 | |
141 void CompilerStats::EnableBenchmark() { | 131 void CompilerStats::EnableBenchmark() { |
142 FLAG_compiler_stats = true; | 132 FLAG_compiler_stats = true; |
143 use_benchmark_output = true; | 133 use_benchmark_output = true; |
144 } | 134 } |
145 | 135 |
146 | |
147 // Generate output for Golem benchmark harness. If the output format | 136 // Generate output for Golem benchmark harness. If the output format |
148 // changes, the parsing function in Golem must be updated. | 137 // changes, the parsing function in Golem must be updated. |
149 char* CompilerStats::BenchmarkOutput() { | 138 char* CompilerStats::BenchmarkOutput() { |
150 Update(); | 139 Update(); |
151 Log log(PrintToStats); | 140 Log log(PrintToStats); |
152 LogBlock lb(Thread::Current(), &log); | 141 LogBlock lb(Thread::Current(), &log); |
153 log.Print("==== Compiler Stats for isolate '%s' ====\n", | 142 log.Print("==== Compiler Stats for isolate '%s' ====\n", |
154 isolate_->debugger_name()); | 143 isolate_->debugger_name()); |
155 | 144 |
156 log.Print("NumberOfTokens: %" Pd64 "\n", num_tokens_total); | 145 log.Print("NumberOfTokens: %" Pd64 "\n", num_tokens_total); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 : 0; | 180 : 0; |
192 | 181 |
193 log.Print("CodeDensity: %" Pd64 " tokens/KB\n", code_density); | 182 log.Print("CodeDensity: %" Pd64 " tokens/KB\n", code_density); |
194 log.Print("InstrSize: %" Pd64 " KB\n", total_instr_size / 1024); | 183 log.Print("InstrSize: %" Pd64 " KB\n", total_instr_size / 1024); |
195 log.Flush(); | 184 log.Flush(); |
196 char* benchmark_text = text; | 185 char* benchmark_text = text; |
197 text = NULL; | 186 text = NULL; |
198 return benchmark_text; | 187 return benchmark_text; |
199 } | 188 } |
200 | 189 |
201 | |
202 char* CompilerStats::PrintToZone() { | 190 char* CompilerStats::PrintToZone() { |
203 if (!FLAG_compiler_stats) { | 191 if (!FLAG_compiler_stats) { |
204 return NULL; | 192 return NULL; |
205 } else if (use_benchmark_output) { | 193 } else if (use_benchmark_output) { |
206 return BenchmarkOutput(); | 194 return BenchmarkOutput(); |
207 } | 195 } |
208 | 196 |
209 Update(); | 197 Update(); |
210 | 198 |
211 Log log(PrintToStats); | 199 Log log(PrintToStats); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 log.Print(" VarDesc size: %" Pd64 " KB\n", vardesc_size / 1024); | 295 log.Print(" VarDesc size: %" Pd64 " KB\n", vardesc_size / 1024); |
308 log.Flush(); | 296 log.Flush(); |
309 char* stats_text = text; | 297 char* stats_text = text; |
310 text = NULL; | 298 text = NULL; |
311 return stats_text; | 299 return stats_text; |
312 } | 300 } |
313 | 301 |
314 #endif // !PRODUCT | 302 #endif // !PRODUCT |
315 | 303 |
316 } // namespace dart | 304 } // namespace dart |
OLD | NEW |