summaryrefslogtreecommitdiff
path: root/deps/v8/src/heap/code-stats.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/heap/code-stats.cc')
-rw-r--r--deps/v8/src/heap/code-stats.cc220
1 files changed, 220 insertions, 0 deletions
diff --git a/deps/v8/src/heap/code-stats.cc b/deps/v8/src/heap/code-stats.cc
new file mode 100644
index 0000000000..d4ff5fbba7
--- /dev/null
+++ b/deps/v8/src/heap/code-stats.cc
@@ -0,0 +1,220 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/heap/code-stats.h"
+#include "src/objects-inl.h"
+
+namespace v8 {
+namespace internal {
+
+// Record code statisitcs.
+void CodeStatistics::RecordCodeAndMetadataStatistics(HeapObject* object,
+ Isolate* isolate) {
+ if (!object->IsAbstractCode()) {
+ return;
+ }
+
+ // Record code+metadata statisitcs.
+ AbstractCode* abstract_code = AbstractCode::cast(object);
+ int size = abstract_code->SizeIncludingMetadata();
+ if (abstract_code->IsCode()) {
+ size += isolate->code_and_metadata_size();
+ isolate->set_code_and_metadata_size(size);
+ } else {
+ size += isolate->bytecode_and_metadata_size();
+ isolate->set_bytecode_and_metadata_size(size);
+ }
+
+#ifdef DEBUG
+ // Record code kind and code comment statistics.
+ isolate->code_kind_statistics()[abstract_code->kind()] +=
+ abstract_code->Size();
+ CodeStatistics::CollectCodeCommentStatistics(object, isolate);
+#endif
+}
+
+void CodeStatistics::ResetCodeAndMetadataStatistics(Isolate* isolate) {
+ isolate->set_code_and_metadata_size(0);
+ isolate->set_bytecode_and_metadata_size(0);
+#ifdef DEBUG
+ ResetCodeStatistics(isolate);
+#endif
+}
+
+// Collects code size statistics:
+// - code and metadata size
+// - by code kind (only in debug mode)
+// - by code comment (only in debug mode)
+void CodeStatistics::CollectCodeStatistics(PagedSpace* space,
+ Isolate* isolate) {
+ HeapObjectIterator obj_it(space);
+ for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) {
+ RecordCodeAndMetadataStatistics(obj, isolate);
+ }
+}
+
+// Collects code size statistics in LargeObjectSpace:
+// - code and metadata size
+// - by code kind (only in debug mode)
+// - by code comment (only in debug mode)
+void CodeStatistics::CollectCodeStatistics(LargeObjectSpace* space,
+ Isolate* isolate) {
+ LargeObjectIterator obj_it(space);
+ for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) {
+ RecordCodeAndMetadataStatistics(obj, isolate);
+ }
+}
+
+#ifdef DEBUG
+void CodeStatistics::ReportCodeStatistics(Isolate* isolate) {
+ // Report code kind statistics
+ int* code_kind_statistics = isolate->code_kind_statistics();
+ PrintF("\n Code kind histograms: \n");
+ for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) {
+ if (code_kind_statistics[i] > 0) {
+ PrintF(" %-20s: %10d bytes\n",
+ AbstractCode::Kind2String(static_cast<AbstractCode::Kind>(i)),
+ code_kind_statistics[i]);
+ }
+ }
+ PrintF("\n");
+
+ // Report code and metadata statisitcs
+ if (isolate->code_and_metadata_size() > 0) {
+ PrintF("Code size including metadata : %10d bytes\n",
+ isolate->code_and_metadata_size());
+ }
+ if (isolate->bytecode_and_metadata_size() > 0) {
+ PrintF("Bytecode size including metadata: %10d bytes\n",
+ isolate->bytecode_and_metadata_size());
+ }
+
+ // Report code comment statistics
+ CommentStatistic* comments_statistics =
+ isolate->paged_space_comments_statistics();
+ PrintF(
+ "Code comment statistics (\" [ comment-txt : size/ "
+ "count (average)\"):\n");
+ for (int i = 0; i <= CommentStatistic::kMaxComments; i++) {
+ const CommentStatistic& cs = comments_statistics[i];
+ if (cs.size > 0) {
+ PrintF(" %-30s: %10d/%6d (%d)\n", cs.comment, cs.size, cs.count,
+ cs.size / cs.count);
+ }
+ }
+ PrintF("\n");
+}
+
+void CodeStatistics::ResetCodeStatistics(Isolate* isolate) {
+ // Clear code kind statistics
+ int* code_kind_statistics = isolate->code_kind_statistics();
+ for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) {
+ code_kind_statistics[i] = 0;
+ }
+
+ // Clear code comment statistics
+ CommentStatistic* comments_statistics =
+ isolate->paged_space_comments_statistics();
+ for (int i = 0; i < CommentStatistic::kMaxComments; i++) {
+ comments_statistics[i].Clear();
+ }
+ comments_statistics[CommentStatistic::kMaxComments].comment = "Unknown";
+ comments_statistics[CommentStatistic::kMaxComments].size = 0;
+ comments_statistics[CommentStatistic::kMaxComments].count = 0;
+}
+
+// Adds comment to 'comment_statistics' table. Performance OK as long as
+// 'kMaxComments' is small
+void CodeStatistics::EnterComment(Isolate* isolate, const char* comment,
+ int delta) {
+ CommentStatistic* comments_statistics =
+ isolate->paged_space_comments_statistics();
+ // Do not count empty comments
+ if (delta <= 0) return;
+ CommentStatistic* cs = &comments_statistics[CommentStatistic::kMaxComments];
+ // Search for a free or matching entry in 'comments_statistics': 'cs'
+ // points to result.
+ for (int i = 0; i < CommentStatistic::kMaxComments; i++) {
+ if (comments_statistics[i].comment == NULL) {
+ cs = &comments_statistics[i];
+ cs->comment = comment;
+ break;
+ } else if (strcmp(comments_statistics[i].comment, comment) == 0) {
+ cs = &comments_statistics[i];
+ break;
+ }
+ }
+ // Update entry for 'comment'
+ cs->size += delta;
+ cs->count += 1;
+}
+
+// Call for each nested comment start (start marked with '[ xxx', end marked
+// with ']'. RelocIterator 'it' must point to a comment reloc info.
+void CodeStatistics::CollectCommentStatistics(Isolate* isolate,
+ RelocIterator* it) {
+ DCHECK(!it->done());
+ DCHECK(it->rinfo()->rmode() == RelocInfo::COMMENT);
+ const char* tmp = reinterpret_cast<const char*>(it->rinfo()->data());
+ if (tmp[0] != '[') {
+ // Not a nested comment; skip
+ return;
+ }
+
+ // Search for end of nested comment or a new nested comment
+ const char* const comment_txt =
+ reinterpret_cast<const char*>(it->rinfo()->data());
+ const byte* prev_pc = it->rinfo()->pc();
+ int flat_delta = 0;
+ it->next();
+ while (true) {
+ // All nested comments must be terminated properly, and therefore exit
+ // from loop.
+ DCHECK(!it->done());
+ if (it->rinfo()->rmode() == RelocInfo::COMMENT) {
+ const char* const txt =
+ reinterpret_cast<const char*>(it->rinfo()->data());
+ flat_delta += static_cast<int>(it->rinfo()->pc() - prev_pc);
+ if (txt[0] == ']') break; // End of nested comment
+ // A new comment
+ CollectCommentStatistics(isolate, it);
+ // Skip code that was covered with previous comment
+ prev_pc = it->rinfo()->pc();
+ }
+ it->next();
+ }
+ EnterComment(isolate, comment_txt, flat_delta);
+}
+
+// Collects code comment statistics
+void CodeStatistics::CollectCodeCommentStatistics(HeapObject* obj,
+ Isolate* isolate) {
+ // Bytecode objects do not contain RelocInfo. Only process code objects
+ // for code comment statistics.
+ if (!obj->IsCode()) {
+ return;
+ }
+
+ Code* code = Code::cast(obj);
+ RelocIterator it(code);
+ int delta = 0;
+ const byte* prev_pc = code->instruction_start();
+ while (!it.done()) {
+ if (it.rinfo()->rmode() == RelocInfo::COMMENT) {
+ delta += static_cast<int>(it.rinfo()->pc() - prev_pc);
+ CollectCommentStatistics(isolate, &it);
+ prev_pc = it.rinfo()->pc();
+ }
+ it.next();
+ }
+
+ DCHECK(code->instruction_start() <= prev_pc &&
+ prev_pc <= code->instruction_end());
+ delta += static_cast<int>(code->instruction_end() - prev_pc);
+ EnterComment(isolate, "NoComment", delta);
+}
+#endif
+
+} // namespace internal
+} // namespace v8