Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/heap/code-stats.h"
6 :
7 : #include "src/code-comments.h"
8 : #include "src/objects-inl.h"
9 : #include "src/reloc-info.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 : // Record code statisitcs.
15 0 : void CodeStatistics::RecordCodeAndMetadataStatistics(HeapObject object,
16 0 : Isolate* isolate) {
17 0 : if (object->IsScript()) {
18 0 : Script script = Script::cast(object);
19 : // Log the size of external source code.
20 0 : Object source = script->source();
21 0 : if (source->IsExternalString()) {
22 0 : ExternalString external_source_string = ExternalString::cast(source);
23 : int size = isolate->external_script_source_size();
24 0 : size += external_source_string->ExternalPayloadSize();
25 : isolate->set_external_script_source_size(size);
26 : }
27 0 : } else if (object->IsAbstractCode()) {
28 : // Record code+metadata statisitcs.
29 0 : AbstractCode abstract_code = AbstractCode::cast(object);
30 0 : int size = abstract_code->SizeIncludingMetadata();
31 0 : if (abstract_code->IsCode()) {
32 0 : size += isolate->code_and_metadata_size();
33 : isolate->set_code_and_metadata_size(size);
34 : } else {
35 0 : size += isolate->bytecode_and_metadata_size();
36 : isolate->set_bytecode_and_metadata_size(size);
37 : }
38 :
39 : #ifdef DEBUG
40 : // Record code kind and code comment statistics.
41 : isolate->code_kind_statistics()[abstract_code->kind()] +=
42 : abstract_code->Size();
43 : CodeStatistics::CollectCodeCommentStatistics(object, isolate);
44 : #endif
45 : }
46 0 : }
47 :
48 0 : void CodeStatistics::ResetCodeAndMetadataStatistics(Isolate* isolate) {
49 : isolate->set_code_and_metadata_size(0);
50 : isolate->set_bytecode_and_metadata_size(0);
51 : isolate->set_external_script_source_size(0);
52 : #ifdef DEBUG
53 : ResetCodeStatistics(isolate);
54 : #endif
55 0 : }
56 :
57 : // Collects code size statistics:
58 : // - code and metadata size
59 : // - by code kind (only in debug mode)
60 : // - by code comment (only in debug mode)
61 0 : void CodeStatistics::CollectCodeStatistics(PagedSpace* space,
62 : Isolate* isolate) {
63 0 : HeapObjectIterator obj_it(space);
64 0 : for (HeapObject obj = obj_it.Next(); !obj.is_null(); obj = obj_it.Next()) {
65 0 : RecordCodeAndMetadataStatistics(obj, isolate);
66 : }
67 0 : }
68 :
69 : // Collects code size statistics in LargeObjectSpace:
70 : // - code and metadata size
71 : // - by code kind (only in debug mode)
72 : // - by code comment (only in debug mode)
73 0 : void CodeStatistics::CollectCodeStatistics(LargeObjectSpace* space,
74 : Isolate* isolate) {
75 0 : LargeObjectIterator obj_it(space);
76 0 : for (HeapObject obj = obj_it.Next(); !obj.is_null(); obj = obj_it.Next()) {
77 0 : RecordCodeAndMetadataStatistics(obj, isolate);
78 : }
79 0 : }
80 :
81 : #ifdef DEBUG
82 : void CodeStatistics::ReportCodeStatistics(Isolate* isolate) {
83 : // Report code kind statistics
84 : int* code_kind_statistics = isolate->code_kind_statistics();
85 : PrintF("\n Code kind histograms: \n");
86 : for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) {
87 : if (code_kind_statistics[i] > 0) {
88 : PrintF(" %-20s: %10d bytes\n",
89 : AbstractCode::Kind2String(static_cast<AbstractCode::Kind>(i)),
90 : code_kind_statistics[i]);
91 : }
92 : }
93 : PrintF("\n");
94 :
95 : // Report code and metadata statisitcs
96 : if (isolate->code_and_metadata_size() > 0) {
97 : PrintF("Code size including metadata : %10d bytes\n",
98 : isolate->code_and_metadata_size());
99 : }
100 : if (isolate->bytecode_and_metadata_size() > 0) {
101 : PrintF("Bytecode size including metadata: %10d bytes\n",
102 : isolate->bytecode_and_metadata_size());
103 : }
104 :
105 : // Report code comment statistics
106 : CommentStatistic* comments_statistics =
107 : isolate->paged_space_comments_statistics();
108 : PrintF(
109 : "Code comment statistics (\" [ comment-txt : size/ "
110 : "count (average)\"):\n");
111 : for (int i = 0; i <= CommentStatistic::kMaxComments; i++) {
112 : const CommentStatistic& cs = comments_statistics[i];
113 : if (cs.size > 0) {
114 : PrintF(" %-30s: %10d/%6d (%d)\n", cs.comment, cs.size, cs.count,
115 : cs.size / cs.count);
116 : }
117 : }
118 : PrintF("\n");
119 : }
120 :
121 : void CodeStatistics::ResetCodeStatistics(Isolate* isolate) {
122 : // Clear code kind statistics
123 : int* code_kind_statistics = isolate->code_kind_statistics();
124 : for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) {
125 : code_kind_statistics[i] = 0;
126 : }
127 :
128 : // Clear code comment statistics
129 : CommentStatistic* comments_statistics =
130 : isolate->paged_space_comments_statistics();
131 : for (int i = 0; i < CommentStatistic::kMaxComments; i++) {
132 : comments_statistics[i].Clear();
133 : }
134 : comments_statistics[CommentStatistic::kMaxComments].comment = "Unknown";
135 : comments_statistics[CommentStatistic::kMaxComments].size = 0;
136 : comments_statistics[CommentStatistic::kMaxComments].count = 0;
137 : }
138 :
139 : // Adds comment to 'comment_statistics' table. Performance OK as long as
140 : // 'kMaxComments' is small
141 : void CodeStatistics::EnterComment(Isolate* isolate, const char* comment,
142 : int delta) {
143 : CommentStatistic* comments_statistics =
144 : isolate->paged_space_comments_statistics();
145 : // Do not count empty comments
146 : if (delta <= 0) return;
147 : CommentStatistic* cs = &comments_statistics[CommentStatistic::kMaxComments];
148 : // Search for a free or matching entry in 'comments_statistics': 'cs'
149 : // points to result.
150 : for (int i = 0; i < CommentStatistic::kMaxComments; i++) {
151 : if (comments_statistics[i].comment == nullptr) {
152 : cs = &comments_statistics[i];
153 : cs->comment = comment;
154 : break;
155 : } else if (strcmp(comments_statistics[i].comment, comment) == 0) {
156 : cs = &comments_statistics[i];
157 : break;
158 : }
159 : }
160 : // Update entry for 'comment'
161 : cs->size += delta;
162 : cs->count += 1;
163 : }
164 :
165 : // Call for each nested comment start (start marked with '[ xxx', end marked
166 : // with ']'. RelocIterator 'it' must point to a comment reloc info.
167 : void CodeStatistics::CollectCommentStatistics(Isolate* isolate,
168 : CodeCommentsIterator* cit) {
169 : DCHECK(cit->HasCurrent());
170 : const char* comment_txt = cit->GetComment();
171 : if (comment_txt[0] != '[') {
172 : // Not a nested comment; skip
173 : return;
174 : }
175 :
176 : // Search for end of nested comment or a new nested comment
177 : int prev_pc_offset = cit->GetPCOffset();
178 : int flat_delta = 0;
179 : cit->Next();
180 : for (; cit->HasCurrent(); cit->Next()) {
181 : // All nested comments must be terminated properly, and therefore exit
182 : // from loop.
183 : const char* const txt = cit->GetComment();
184 : flat_delta += cit->GetPCOffset() - prev_pc_offset;
185 : if (txt[0] == ']') break; // End of nested comment
186 : // A new comment
187 : CollectCommentStatistics(isolate, cit);
188 : // Skip code that was covered with previous comment
189 : prev_pc_offset = cit->GetPCOffset();
190 : }
191 : EnterComment(isolate, comment_txt, flat_delta);
192 : }
193 :
194 : // Collects code comment statistics
195 : void CodeStatistics::CollectCodeCommentStatistics(HeapObject obj,
196 : Isolate* isolate) {
197 : // Bytecode objects do not contain RelocInfo. Only process code objects
198 : // for code comment statistics.
199 : if (!obj->IsCode()) {
200 : return;
201 : }
202 :
203 : Code code = Code::cast(obj);
204 : CodeCommentsIterator cit(code->code_comments());
205 : int delta = 0;
206 : int prev_pc_offset = 0;
207 : while (cit.HasCurrent()) {
208 : delta += static_cast<int>(cit.GetPCOffset() - prev_pc_offset);
209 : CollectCommentStatistics(isolate, &cit);
210 : prev_pc_offset = cit.GetPCOffset();
211 : cit.Next();
212 : }
213 :
214 : DCHECK(0 <= prev_pc_offset && prev_pc_offset <= code->raw_instruction_size());
215 : delta += static_cast<int>(code->raw_instruction_size() - prev_pc_offset);
216 : EnterComment(isolate, "NoComment", delta);
217 : }
218 : #endif
219 :
220 : } // namespace internal
221 183867 : } // namespace v8
|