// 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/code-comments.h"
#include "src/heap/spaces-inl.h"  // For HeapObjectIterator.
#include "src/objects-inl.h"
#include "src/reloc-info.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) {
  HeapObjectIterator 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) {
  LargeObjectIterator 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());
  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
