// 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/profiler/profiler-listener.h"

#include "src/deoptimizer.h"
#include "src/interpreter/source-position-table.h"
#include "src/profiler/cpu-profiler.h"
#include "src/profiler/profile-generator-inl.h"

namespace v8 {
namespace internal {

ProfilerListener::ProfilerListener(Isolate* isolate)
    : function_and_resource_names_(isolate->heap()) {}

ProfilerListener::~ProfilerListener() {
  for (auto code_entry : code_entries_) {
    delete code_entry;
  }
}

void ProfilerListener::CallbackEvent(Name* name, Address entry_point) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
  rec->start = entry_point;
  rec->entry = NewCodeEntry(CodeEventListener::CALLBACK_TAG, GetName(name));
  rec->size = 1;
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* code, const char* name) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
  rec->start = code->address();
  rec->entry = NewCodeEntry(
      tag, GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
  RecordInliningInfo(rec->entry, code);
  rec->size = code->ExecutableSize();
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* code, Name* name) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
  rec->start = code->address();
  rec->entry = NewCodeEntry(
      tag, GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
  RecordInliningInfo(rec->entry, code);
  rec->size = code->ExecutableSize();
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* code,
                                       SharedFunctionInfo* shared,
                                       Name* script_name) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
  rec->start = code->address();
  rec->entry = NewCodeEntry(
      tag, GetFunctionName(shared->DebugName()), CodeEntry::kEmptyNamePrefix,
      GetName(InferScriptName(script_name, shared)),
      CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo,
      NULL, code->instruction_start());
  RecordInliningInfo(rec->entry, code);
  rec->entry->FillFunctionInfo(shared);
  rec->size = code->ExecutableSize();
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* abstract_code,
                                       SharedFunctionInfo* shared,
                                       Name* script_name, int line,
                                       int column) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
  rec->start = abstract_code->address();
  Script* script = Script::cast(shared->script());
  JITLineInfoTable* line_table = NULL;
  if (script) {
    if (abstract_code->IsCode()) {
      Code* code = abstract_code->GetCode();
      int start_position = shared->start_position();
      int end_position = shared->end_position();
      line_table = new JITLineInfoTable();
      for (RelocIterator it(code); !it.done(); it.next()) {
        RelocInfo* reloc_info = it.rinfo();
        if (!RelocInfo::IsPosition(reloc_info->rmode())) continue;
        int position = static_cast<int>(reloc_info->data());
        // TODO(alph): in case of inlining the position may correspond
        // to an inlined function source code. Do not collect positions
        // that fall beyond the function source code. There's however a
        // chance the inlined function has similar positions but in another
        // script. So the proper fix is to store script_id in some form
        // along with the inlined function positions.
        if (position < start_position || position >= end_position) continue;
        int pc_offset = static_cast<int>(reloc_info->pc() - code->address());
        int line_number = script->GetLineNumber(position) + 1;
        line_table->SetPosition(pc_offset, line_number);
      }
    } else {
      BytecodeArray* bytecode = abstract_code->GetBytecodeArray();
      line_table = new JITLineInfoTable();
      interpreter::SourcePositionTableIterator it(
          bytecode->source_position_table());
      for (; !it.done(); it.Advance()) {
        int line_number = script->GetLineNumber(it.source_position()) + 1;
        int pc_offset = it.bytecode_offset() + BytecodeArray::kHeaderSize;
        line_table->SetPosition(pc_offset, line_number);
      }
    }
  }
  rec->entry = NewCodeEntry(
      tag, GetFunctionName(shared->DebugName()), CodeEntry::kEmptyNamePrefix,
      GetName(InferScriptName(script_name, shared)), line, column, line_table,
      abstract_code->instruction_start());
  RecordInliningInfo(rec->entry, abstract_code);
  RecordDeoptInlinedFrames(rec->entry, abstract_code);
  rec->entry->FillFunctionInfo(shared);
  rec->size = abstract_code->ExecutableSize();
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* code, int args_count) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
  rec->start = code->address();
  rec->entry = NewCodeEntry(
      tag, GetName(args_count), "args_count: ", CodeEntry::kEmptyResourceName,
      CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo,
      NULL, code->instruction_start());
  RecordInliningInfo(rec->entry, code);
  rec->size = code->ExecutableSize();
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::CodeMoveEvent(AbstractCode* from, Address to) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
  CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
  rec->from = from->address();
  rec->to = to;
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::CodeDisableOptEvent(AbstractCode* code,
                                           SharedFunctionInfo* shared) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_DISABLE_OPT);
  CodeDisableOptEventRecord* rec = &evt_rec.CodeDisableOptEventRecord_;
  rec->start = code->address();
  rec->bailout_reason = GetBailoutReason(shared->disable_optimization_reason());
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::CodeDeoptEvent(Code* code, Address pc,
                                      int fp_to_sp_delta) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_DEOPT);
  CodeDeoptEventRecord* rec = &evt_rec.CodeDeoptEventRecord_;
  Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(code, pc);
  rec->start = code->address();
  rec->deopt_reason = Deoptimizer::GetDeoptReason(info.deopt_reason);
  rec->position = info.position;
  rec->deopt_id = info.deopt_id;
  rec->pc = reinterpret_cast<void*>(pc);
  rec->fp_to_sp_delta = fp_to_sp_delta;
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::GetterCallbackEvent(Name* name, Address entry_point) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
  rec->start = entry_point;
  rec->entry =
      NewCodeEntry(CodeEventListener::CALLBACK_TAG, GetName(name), "get ");
  rec->size = 1;
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::RegExpCodeCreateEvent(AbstractCode* code,
                                             String* source) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
  rec->start = code->address();
  rec->entry = NewCodeEntry(
      CodeEventListener::REG_EXP_TAG, GetName(source), "RegExp: ",
      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
  rec->size = code->ExecutableSize();
  DispatchCodeEvent(evt_rec);
}

void ProfilerListener::SetterCallbackEvent(Name* name, Address entry_point) {
  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
  rec->start = entry_point;
  rec->entry =
      NewCodeEntry(CodeEventListener::CALLBACK_TAG, GetName(name), "set ");
  rec->size = 1;
  DispatchCodeEvent(evt_rec);
}

Name* ProfilerListener::InferScriptName(Name* name, SharedFunctionInfo* info) {
  if (name->IsString() && String::cast(name)->length()) return name;
  if (!info->script()->IsScript()) return name;
  Object* source_url = Script::cast(info->script())->source_url();
  return source_url->IsName() ? Name::cast(source_url) : name;
}

void ProfilerListener::RecordInliningInfo(CodeEntry* entry,
                                          AbstractCode* abstract_code) {
  if (!abstract_code->IsCode()) return;
  Code* code = abstract_code->GetCode();
  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;
  DeoptimizationInputData* deopt_input_data =
      DeoptimizationInputData::cast(code->deoptimization_data());
  int deopt_count = deopt_input_data->DeoptCount();
  for (int i = 0; i < deopt_count; i++) {
    int pc_offset = deopt_input_data->Pc(i)->value();
    if (pc_offset == -1) continue;
    int translation_index = deopt_input_data->TranslationIndex(i)->value();
    TranslationIterator it(deopt_input_data->TranslationByteArray(),
                           translation_index);
    Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
    DCHECK_EQ(Translation::BEGIN, opcode);
    it.Skip(Translation::NumberOfOperandsFor(opcode));
    int depth = 0;
    std::vector<CodeEntry*> inline_stack;
    while (it.HasNext() &&
           Translation::BEGIN !=
               (opcode = static_cast<Translation::Opcode>(it.Next()))) {
      if (opcode != Translation::JS_FRAME &&
          opcode != Translation::INTERPRETED_FRAME) {
        it.Skip(Translation::NumberOfOperandsFor(opcode));
        continue;
      }
      it.Next();  // Skip ast_id
      int shared_info_id = it.Next();
      it.Next();  // Skip height
      SharedFunctionInfo* shared_info = SharedFunctionInfo::cast(
          deopt_input_data->LiteralArray()->get(shared_info_id));
      if (!depth++) continue;  // Skip the current function itself.
      CodeEntry* inline_entry = new CodeEntry(
          entry->tag(), GetFunctionName(shared_info->DebugName()),
          CodeEntry::kEmptyNamePrefix, entry->resource_name(),
          CpuProfileNode::kNoLineNumberInfo,
          CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
      inline_entry->FillFunctionInfo(shared_info);
      inline_stack.push_back(inline_entry);
    }
    if (!inline_stack.empty()) {
      entry->AddInlineStack(pc_offset, inline_stack);
      DCHECK(inline_stack.empty());
    }
  }
}

void ProfilerListener::RecordDeoptInlinedFrames(CodeEntry* entry,
                                                AbstractCode* abstract_code) {
  if (abstract_code->kind() != AbstractCode::OPTIMIZED_FUNCTION) return;
  Code* code = abstract_code->GetCode();
  DeoptimizationInputData* deopt_input_data =
      DeoptimizationInputData::cast(code->deoptimization_data());
  int const mask = RelocInfo::ModeMask(RelocInfo::DEOPT_ID);
  for (RelocIterator rit(code, mask); !rit.done(); rit.next()) {
    RelocInfo* reloc_info = rit.rinfo();
    DCHECK(RelocInfo::IsDeoptId(reloc_info->rmode()));
    int deopt_id = static_cast<int>(reloc_info->data());
    int translation_index =
        deopt_input_data->TranslationIndex(deopt_id)->value();
    TranslationIterator it(deopt_input_data->TranslationByteArray(),
                           translation_index);
    Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
    DCHECK_EQ(Translation::BEGIN, opcode);
    it.Skip(Translation::NumberOfOperandsFor(opcode));
    std::vector<CodeEntry::DeoptInlinedFrame> inlined_frames;
    while (it.HasNext() &&
           Translation::BEGIN !=
               (opcode = static_cast<Translation::Opcode>(it.Next()))) {
      if (opcode != Translation::JS_FRAME &&
          opcode != Translation::INTERPRETED_FRAME) {
        it.Skip(Translation::NumberOfOperandsFor(opcode));
        continue;
      }
      BailoutId ast_id = BailoutId(it.Next());
      int shared_info_id = it.Next();
      it.Next();  // Skip height
      SharedFunctionInfo* shared = SharedFunctionInfo::cast(
          deopt_input_data->LiteralArray()->get(shared_info_id));
      int source_position = Deoptimizer::ComputeSourcePosition(shared, ast_id);
      int script_id = v8::UnboundScript::kNoScriptId;
      if (shared->script()->IsScript()) {
        Script* script = Script::cast(shared->script());
        script_id = script->id();
      }
      CodeEntry::DeoptInlinedFrame frame = {source_position, script_id};
      inlined_frames.push_back(frame);
    }
    if (!inlined_frames.empty() && !entry->HasDeoptInlinedFramesFor(deopt_id)) {
      entry->AddDeoptInlinedFrames(deopt_id, inlined_frames);
      DCHECK(inlined_frames.empty());
    }
  }
}

CodeEntry* ProfilerListener::NewCodeEntry(
    CodeEventListener::LogEventsAndTags tag, const char* name,
    const char* name_prefix, const char* resource_name, int line_number,
    int column_number, JITLineInfoTable* line_info, Address instruction_start) {
  CodeEntry* code_entry =
      new CodeEntry(tag, name, name_prefix, resource_name, line_number,
                    column_number, line_info, instruction_start);
  code_entries_.push_back(code_entry);
  return code_entry;
}

void ProfilerListener::AddObserver(CodeEventObserver* observer) {
  if (std::find(observers_.begin(), observers_.end(), observer) !=
      observers_.end())
    return;
  observers_.push_back(observer);
}

void ProfilerListener::RemoveObserver(CodeEventObserver* observer) {
  auto it = std::find(observers_.begin(), observers_.end(), observer);
  if (it == observers_.end()) return;
  observers_.erase(it);
}

}  // namespace internal
}  // namespace v8
