LCOV - code coverage report
Current view: top level - src/heap - code-stats.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1 25 4.0 %
Date: 2019-03-21 Functions: 1 5 20.0 %

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

Generated by: LCOV version 1.10