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