// 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/codegen/code-comments.h"
#include "src/codegen/reloc-info.h"
#include "src/heap/spaces-inl.h"  // For PagedSpaceObjectIterator.
#include "src/objects/objects-inl.h"

namespace v8 {
namespace internal {

// Record code statisitcs.
void CodeStatistics::RecordCodeAndMetadataStatistics(HeapObject object,
                                                     Isolate* isolate) {
  if (object.IsScript()) {
    Script script = Script::cast(object);
    // Log the size of external source code.
    Object source = script.source();
    if (source.IsExternalString()) {
      ExternalString external_source_string = ExternalString::cast(source);
      int size = isolate->external_script_source_size();
      size += external_source_string.ExternalPayloadSize();
      isolate->set_external_script_source_size(size);
    }
  } else if (object.IsAbstractCode()) {
    // 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);
  isolate->set_external_script_source_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) {
  PagedSpaceObjectIterator obj_it(space);
  for (HeapObject obj = obj_it.Next(); !obj.is_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) {
  LargeObjectSpaceObjectIterator obj_it(space);
  for (HeapObject obj = obj_it.Next(); !obj.is_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 == nullptr) {
      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,
                                              CodeCommentsIterator* cit) {
  DCHECK(cit->HasCurrent());
  const char* comment_txt = cit->GetComment();
  if (comment_txt[0] != '[') {
    // Not a nested comment; skip
    return;
  }

  // Search for end of nested comment or a new nested comment
  int prev_pc_offset = cit->GetPCOffset();
  int flat_delta = 0;
  cit->Next();
  for (; cit->HasCurrent(); cit->Next()) {
    // All nested comments must be terminated properly, and therefore exit
    // from loop.
    const char* const txt = cit->GetComment();
    flat_delta += cit->GetPCOffset() - prev_pc_offset;
    if (txt[0] == ']') break;  // End of nested  comment
    // A new comment
    CollectCommentStatistics(isolate, cit);
    // Skip code that was covered with previous comment
    prev_pc_offset = cit->GetPCOffset();
  }
  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);
  CodeCommentsIterator cit(code.code_comments(), code.code_comments_size());
  int delta = 0;
  int prev_pc_offset = 0;
  while (cit.HasCurrent()) {
    delta += static_cast<int>(cit.GetPCOffset() - prev_pc_offset);
    CollectCommentStatistics(isolate, &cit);
    prev_pc_offset = cit.GetPCOffset();
    cit.Next();
  }

  DCHECK(0 <= prev_pc_offset && prev_pc_offset <= code.raw_instruction_size());
  delta += static_cast<int>(code.raw_instruction_size() - prev_pc_offset);
  EnterComment(isolate, "NoComment", delta);
}
#endif

}  // namespace internal
}  // namespace v8
