Flutter Engine
The Flutter Engine
code_statistics.cc
Go to the documentation of this file.
1// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
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.
4
6
7namespace dart {
8
10 unaccounted_bytes_ = 0;
11 alignment_bytes_ = 0;
12 object_header_bytes_ = 0;
13 return_const_count_ = 0;
14 return_const_with_load_field_count_ = 0;
15 intptr_t i = 0;
16
17#define DO(type, attrs) \
18 entries_[i].name = #type; \
19 entries_[i].bytes = 0; \
20 entries_[i++].count = 0;
21
23
24#undef DO
25
26#define DO(type, attrs) \
27 entries_[i].name = "SlowPath:" #type; \
28 entries_[i].bytes = 0; \
29 entries_[i++].count = 0;
30
32
33#undef DO
34
35#define INIT_SPECIAL_ENTRY(tag, str) \
36 entries_[tag].name = str; \
37 entries_[tag].bytes = 0; \
38 entries_[tag].count = 0;
39
41 "AssertAssignable:ParameterCheck");
43 "AssertAssignable:InsertedByFrontend");
45 "AssertAssignable:FromSource");
46
47 INIT_SPECIAL_ENTRY(kTagCheckedEntry, "<checked-entry-prologue>");
48 INIT_SPECIAL_ENTRY(kTagIntrinsics, "<intrinsics>");
49#undef INIT_SPECIAL_ENTRY
50}
51
53 ASSERT(unaccounted_bytes_ >= 0);
54
55 Entry* sorted[kNumEntries];
56 for (intptr_t i = 0; i < kNumEntries; i++) {
57 sorted[i] = &entries_[i];
58 }
59 qsort(sorted, kNumEntries, sizeof(Entry*), &CompareEntries);
60
61 intptr_t instruction_bytes = 0;
62 for (intptr_t i = 0; i < kNumEntries; i++) {
63 instruction_bytes += entries_[i].bytes;
64 }
65 intptr_t total = object_header_bytes_ + instruction_bytes +
66 unaccounted_bytes_ + alignment_bytes_;
67 float ftotal = static_cast<float>(total) / 100.0;
68
69 OS::PrintErr("--------------------\n");
70
71 for (intptr_t i = 0; i < kNumEntries; i++) {
72 Entry* entry = sorted[i];
73 const char* name = entry->name;
74 intptr_t bytes = entry->bytes;
75 intptr_t count = entry->count;
76 float percent = bytes / ftotal;
77 float avg = static_cast<float>(bytes) / count;
78 if (bytes > 0) {
80 "%5.2f %% "
81 "% 8" Pd
82 " bytes "
83 "% 8" Pd
84 " count "
85 "%8.2f avg bytes/entry "
86 "- %s\n",
87 percent, bytes, count, avg, name);
88 }
89 }
90
91 OS::PrintErr("--------------------\n");
92
93 OS::PrintErr("%5.2f %% % 8" Pd " bytes unaccounted\n",
94 unaccounted_bytes_ / ftotal, unaccounted_bytes_);
95 OS::PrintErr("%5.2f %% % 8" Pd " bytes alignment\n",
96 alignment_bytes_ / ftotal, alignment_bytes_);
97 OS::PrintErr("%5.2f %% % 8" Pd " bytes instruction object header\n",
98 object_header_bytes_ / ftotal, object_header_bytes_);
99 OS::PrintErr("%5.2f %% % 8" Pd " bytes instructions\n",
100 instruction_bytes / ftotal, instruction_bytes);
101 OS::PrintErr("--------------------\n");
102 OS::PrintErr("%5.2f %% % 8" Pd " bytes in total\n", total / ftotal, total);
103 OS::PrintErr("--------------------\n");
104 OS::PrintErr("% 8" Pd " return-constant functions\n", return_const_count_);
105 OS::PrintErr("% 8" Pd " return-constant-with-load-field functions\n",
106 return_const_with_load_field_count_);
107 OS::PrintErr("--------------------\n");
108}
109
110int CombinedCodeStatistics::CompareEntries(const void* a, const void* b) {
111 const intptr_t a_size = (*static_cast<const Entry* const*>(a))->bytes;
112 const intptr_t b_size = (*static_cast<const Entry* const*>(b))->bytes;
113 if (a_size < b_size) {
114 return -1;
115 } else if (a_size > b_size) {
116 return 1;
117 } else {
118 return 0;
119 }
120}
121
123 : assembler_(assembler) {
124 memset(entries_, 0, CombinedCodeStatistics::kNumEntries * sizeof(Entry));
125 instruction_bytes_ = 0;
126 unaccounted_bytes_ = 0;
127 alignment_bytes_ = 0;
128
129 stack_index_ = -1;
130 for (intptr_t i = 0; i < kStackSize; i++)
131 stack_[i] = -1;
132}
133
135 SpecialBegin(static_cast<intptr_t>(instruction->statistics_tag()));
136}
137
139 SpecialEnd(static_cast<intptr_t>(instruction->statistics_tag()));
140}
141
143 stack_index_++;
144 RELEASE_ASSERT(stack_index_ < kStackSize);
145 RELEASE_ASSERT(stack_[stack_index_] == -1);
147 stack_[stack_index_] = assembler_->CodeSize();
148 RELEASE_ASSERT(stack_[stack_index_] >= 0);
149}
150
151void CodeStatistics::SpecialEnd(intptr_t tag) {
152 RELEASE_ASSERT(stack_index_ > 0 || stack_[stack_index_] >= 0);
154
155 intptr_t diff = assembler_->CodeSize() - stack_[stack_index_];
156 RELEASE_ASSERT(diff >= 0);
157 RELEASE_ASSERT(entries_[tag].bytes >= 0);
158 RELEASE_ASSERT(entries_[tag].count >= 0);
159 entries_[tag].bytes += diff;
160 entries_[tag].count++;
161 instruction_bytes_ += diff;
162 stack_[stack_index_] = -1;
163 stack_index_--;
164}
165
167 intptr_t function_size = assembler_->CodeSize();
168 unaccounted_bytes_ = function_size - instruction_bytes_;
169 ASSERT(unaccounted_bytes_ >= 0);
170
171 const intptr_t unaligned_bytes = Instructions::HeaderSize() + function_size;
172 alignment_bytes_ =
173 Utils::RoundUp(unaligned_bytes, kObjectAlignment) - unaligned_bytes;
174 assembler_ = nullptr;
175}
176
178 bool returns_constant = true;
179 bool returns_const_with_load_field_ = true;
180
181 for (intptr_t i = 0; i < CombinedCodeStatistics::kNumEntries; i++) {
182 intptr_t bytes = entries_[i].bytes;
183 stat->entries_[i].count += entries_[i].count;
184 if (bytes > 0) {
185 stat->entries_[i].bytes += bytes;
186 if (i != CombinedCodeStatistics::kTagParallelMove &&
187 i != CombinedCodeStatistics::kTagDartReturn &&
188 i != CombinedCodeStatistics::kTagCheckStackOverflow &&
189 i != CombinedCodeStatistics::kTagCheckStackOverflowSlowPath) {
190 returns_constant = false;
191 if (i != CombinedCodeStatistics::kTagLoadField &&
192 i != CombinedCodeStatistics::kTagTargetEntry &&
193 i != CombinedCodeStatistics::kTagJoinEntry) {
194 returns_const_with_load_field_ = false;
195 }
196 }
197 }
198 }
199 stat->unaccounted_bytes_ += unaccounted_bytes_;
200 ASSERT(stat->unaccounted_bytes_ >= 0);
201 stat->alignment_bytes_ += alignment_bytes_;
202 stat->object_header_bytes_ += Instructions::HeaderSize();
203
204 if (returns_constant) stat->return_const_count_++;
205 if (returns_const_with_load_field_) {
206 stat->return_const_with_load_field_count_++;
207 }
208}
209
210} // namespace dart
int count
Definition: FontMgrTest.cpp:50
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
void End(Instruction *instruction)
void AppendTo(CombinedCodeStatistics *stat)
void SpecialBegin(intptr_t tag)
void SpecialEnd(intptr_t tag)
void Begin(Instruction *instruction)
CodeStatistics(compiler::Assembler *assembler)
virtual intptr_t statistics_tag() const
Definition: il.h:991
static intptr_t HeaderSize()
Definition: object.h:5825
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:120
#define INIT_SPECIAL_ENTRY(tag, str)
#define DO(type, attrs)
#define ASSERT(E)
static bool b
struct MyStruct a[10]
#define FOR_EACH_INSTRUCTION(M)
Definition: il.h:405
Definition: dart_vm.cc:33
const char *const name
static constexpr intptr_t kObjectAlignment
#define Pd
Definition: globals.h:408