// Copyright 2011 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/logging/log.h"

#include <cstdarg>
#include <memory>
#include <sstream>

#include "src/api/api-inl.h"
#include "src/base/platform/platform.h"
#include "src/codegen/bailout-reason.h"
#include "src/codegen/macro-assembler.h"
#include "src/codegen/source-position-table.h"
#include "src/deoptimizer/deoptimizer.h"
#include "src/diagnostics/perf-jit.h"
#include "src/execution/isolate.h"
#include "src/execution/runtime-profiler.h"
#include "src/execution/vm-state-inl.h"
#include "src/handles/global-handles.h"
#include "src/init/bootstrapper.h"
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/interpreter.h"
#include "src/libsampler/sampler.h"
#include "src/logging/counters.h"
#include "src/logging/log-inl.h"
#include "src/logging/log-utils.h"
#include "src/objects/api-callbacks.h"
#include "src/profiler/tick-sample.h"
#include "src/snapshot/embedded/embedded-data.h"
#include "src/strings/string-stream.h"
#include "src/strings/unicode-inl.h"
#include "src/tracing/tracing-category-observer.h"
#include "src/utils/memcopy.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-objects-inl.h"

#include "src/utils/version.h"

namespace v8 {
namespace internal {

#define DECLARE_EVENT(ignore1, name) #name,
static const char* kLogEventsNames[CodeEventListener::NUMBER_OF_LOG_EVENTS] = {
    LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)};
#undef DECLARE_EVENT

static v8::CodeEventType GetCodeEventTypeForTag(
    CodeEventListener::LogEventsAndTags tag) {
  switch (tag) {
    case CodeEventListener::NUMBER_OF_LOG_EVENTS:
#define V(Event, _) case CodeEventListener::Event:
      LOG_EVENTS_LIST(V)
#undef V
      return v8::CodeEventType::kUnknownType;
#define V(From, To)             \
  case CodeEventListener::From: \
    return v8::CodeEventType::k##To##Type;
      TAGS_LIST(V)
#undef V
  }
  // The execution should never pass here
  UNREACHABLE();
  // NOTE(mmarchini): Workaround to fix a compiler failure on GCC 4.9
  return v8::CodeEventType::kUnknownType;
}
#define CALL_CODE_EVENT_HANDLER(Call) \
  if (listener_) {                    \
    listener_->Call;                  \
  } else {                            \
    PROFILE(isolate_, Call);          \
  }

static const char* ComputeMarker(SharedFunctionInfo shared, AbstractCode code) {
  switch (code.kind()) {
    case AbstractCode::INTERPRETED_FUNCTION:
      return shared.optimization_disabled() ? "" : "~";
    case AbstractCode::OPTIMIZED_FUNCTION:
      return "*";
    default:
      return "";
  }
}

static const char* ComputeMarker(const wasm::WasmCode* code) {
  switch (code->kind()) {
    case wasm::WasmCode::kFunction:
      return code->is_liftoff() ? "" : "*";
    case wasm::WasmCode::kInterpreterEntry:
      return "~";
    default:
      return "";
  }
}

class CodeEventLogger::NameBuffer {
 public:
  NameBuffer() { Reset(); }

  void Reset() { utf8_pos_ = 0; }

  void Init(CodeEventListener::LogEventsAndTags tag) {
    Reset();
    AppendBytes(kLogEventsNames[tag]);
    AppendByte(':');
  }

  void AppendName(Name name) {
    if (name.IsString()) {
      AppendString(String::cast(name));
    } else {
      Symbol symbol = Symbol::cast(name);
      AppendBytes("symbol(");
      if (!symbol.name().IsUndefined()) {
        AppendBytes("\"");
        AppendString(String::cast(symbol.name()));
        AppendBytes("\" ");
      }
      AppendBytes("hash ");
      AppendHex(symbol.Hash());
      AppendByte(')');
    }
  }

  void AppendString(String str) {
    if (str.is_null()) return;
    int length = 0;
    std::unique_ptr<char[]> c_str =
        str.ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, &length);
    AppendBytes(c_str.get(), length);
  }

  void AppendBytes(const char* bytes, int size) {
    size = Min(size, kUtf8BufferSize - utf8_pos_);
    MemCopy(utf8_buffer_ + utf8_pos_, bytes, size);
    utf8_pos_ += size;
  }

  void AppendBytes(const char* bytes) {
    size_t len = strlen(bytes);
    DCHECK_GE(kMaxInt, len);
    AppendBytes(bytes, static_cast<int>(len));
  }

  void AppendByte(char c) {
    if (utf8_pos_ >= kUtf8BufferSize) return;
    utf8_buffer_[utf8_pos_++] = c;
  }

  void AppendInt(int n) {
    int space = kUtf8BufferSize - utf8_pos_;
    if (space <= 0) return;
    Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
    int size = SNPrintF(buffer, "%d", n);
    if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
      utf8_pos_ += size;
    }
  }

  void AppendHex(uint32_t n) {
    int space = kUtf8BufferSize - utf8_pos_;
    if (space <= 0) return;
    Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
    int size = SNPrintF(buffer, "%x", n);
    if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
      utf8_pos_ += size;
    }
  }

  const char* get() { return utf8_buffer_; }
  int size() const { return utf8_pos_; }

 private:
  static const int kUtf8BufferSize = 512;
  static const int kUtf16BufferSize = kUtf8BufferSize;

  int utf8_pos_;
  char utf8_buffer_[kUtf8BufferSize];
};

CodeEventLogger::CodeEventLogger(Isolate* isolate)
    : isolate_(isolate), name_buffer_(new NameBuffer) {}

CodeEventLogger::~CodeEventLogger() { delete name_buffer_; }

void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                      AbstractCode code, const char* comment) {
  name_buffer_->Init(tag);
  name_buffer_->AppendBytes(comment);
  LogRecordedBuffer(code, SharedFunctionInfo(), name_buffer_->get(),
                    name_buffer_->size());
}

void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                      AbstractCode code, Name name) {
  name_buffer_->Init(tag);
  name_buffer_->AppendName(name);
  LogRecordedBuffer(code, SharedFunctionInfo(), name_buffer_->get(),
                    name_buffer_->size());
}

void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                      AbstractCode code,
                                      SharedFunctionInfo shared, Name name) {
  name_buffer_->Init(tag);
  name_buffer_->AppendBytes(ComputeMarker(shared, code));
  name_buffer_->AppendByte(' ');
  name_buffer_->AppendName(name);
  LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
}

void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                      AbstractCode code,
                                      SharedFunctionInfo shared, Name source,
                                      int line, int column) {
  name_buffer_->Init(tag);
  name_buffer_->AppendBytes(ComputeMarker(shared, code));
  name_buffer_->AppendString(shared.DebugName());
  name_buffer_->AppendByte(' ');
  if (source.IsString()) {
    name_buffer_->AppendString(String::cast(source));
  } else {
    name_buffer_->AppendBytes("symbol(hash ");
    name_buffer_->AppendHex(Name::cast(source).Hash());
    name_buffer_->AppendByte(')');
  }
  name_buffer_->AppendByte(':');
  name_buffer_->AppendInt(line);
  LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
}

void CodeEventLogger::CodeCreateEvent(LogEventsAndTags tag,
                                      const wasm::WasmCode* code,
                                      wasm::WasmName name) {
  name_buffer_->Init(tag);
  if (name.empty()) {
    name_buffer_->AppendBytes("<wasm-unknown>");
  } else {
    name_buffer_->AppendBytes(name.begin(), name.length());
  }
  name_buffer_->AppendByte('-');
  if (code->IsAnonymous()) {
    name_buffer_->AppendBytes("<anonymous>");
  } else {
    name_buffer_->AppendInt(code->index());
  }
  LogRecordedBuffer(code, name_buffer_->get(), name_buffer_->size());
}

void CodeEventLogger::RegExpCodeCreateEvent(AbstractCode code, String source) {
  name_buffer_->Init(CodeEventListener::REG_EXP_TAG);
  name_buffer_->AppendString(source);
  LogRecordedBuffer(code, SharedFunctionInfo(), name_buffer_->get(),
                    name_buffer_->size());
}

// Linux perf tool logging support
class PerfBasicLogger : public CodeEventLogger {
 public:
  explicit PerfBasicLogger(Isolate* isolate);
  ~PerfBasicLogger() override;

  void CodeMoveEvent(AbstractCode from, AbstractCode to) override {}
  void CodeDisableOptEvent(AbstractCode code,
                           SharedFunctionInfo shared) override {}

 private:
  void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
                         const char* name, int length) override;
  void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
                         int length) override;
  void WriteLogRecordedBuffer(uintptr_t address, int size, const char* name,
                              int name_length);

  // Extension added to V8 log file name to get the low-level log name.
  static const char kFilenameFormatString[];
  static const int kFilenameBufferPadding;

  FILE* perf_output_handle_;
};

const char PerfBasicLogger::kFilenameFormatString[] = "/tmp/perf-%d.map";
// Extra space for the PID in the filename
const int PerfBasicLogger::kFilenameBufferPadding = 16;

PerfBasicLogger::PerfBasicLogger(Isolate* isolate)
    : CodeEventLogger(isolate), perf_output_handle_(nullptr) {
  // Open the perf JIT dump file.
  int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
  ScopedVector<char> perf_dump_name(bufferSize);
  int size = SNPrintF(perf_dump_name, kFilenameFormatString,
                      base::OS::GetCurrentProcessId());
  CHECK_NE(size, -1);
#if !defined(V8_OS_STARBOARD)
  perf_output_handle_ =
      base::OS::FOpen(perf_dump_name.begin(), base::OS::LogFileOpenMode);
  CHECK_NOT_NULL(perf_output_handle_);
  setvbuf(perf_output_handle_, nullptr, _IOLBF, 0);
#else
  SB_NOTIMPLEMENTED();
#endif
}

PerfBasicLogger::~PerfBasicLogger() {
#if !defined(V8_OS_STARBOARD)
  fclose(perf_output_handle_);
  perf_output_handle_ = nullptr;
#endif
}

void PerfBasicLogger::WriteLogRecordedBuffer(uintptr_t address, int size,
                                             const char* name,
                                             int name_length) {
  // Linux perf expects hex literals without a leading 0x, while some
  // implementations of printf might prepend one when using the %p format
  // for pointers, leading to wrongly formatted JIT symbols maps.
  //
  // Instead, we use V8PRIxPTR format string and cast pointer to uintpr_t,
  // so that we have control over the exact output format.
  base::OS::FPrint(perf_output_handle_, "%" V8PRIxPTR " %x %.*s\n", address,
                   size, name_length, name);
}

void PerfBasicLogger::LogRecordedBuffer(AbstractCode code, SharedFunctionInfo,
                                        const char* name, int length) {
  if (FLAG_perf_basic_prof_only_functions &&
      (code.kind() != AbstractCode::INTERPRETED_FUNCTION &&
       code.kind() != AbstractCode::BUILTIN &&
       code.kind() != AbstractCode::OPTIMIZED_FUNCTION)) {
    return;
  }

  WriteLogRecordedBuffer(static_cast<uintptr_t>(code.InstructionStart()),
                         code.InstructionSize(), name, length);
}

void PerfBasicLogger::LogRecordedBuffer(const wasm::WasmCode* code,
                                        const char* name, int length) {
  WriteLogRecordedBuffer(static_cast<uintptr_t>(code->instruction_start()),
                         code->instructions().length(), name, length);
}

// External CodeEventListener
ExternalCodeEventListener::ExternalCodeEventListener(Isolate* isolate)
    : is_listening_(false), isolate_(isolate), code_event_handler_(nullptr) {}

ExternalCodeEventListener::~ExternalCodeEventListener() {
  if (is_listening_) {
    StopListening();
  }
}

void ExternalCodeEventListener::LogExistingCode() {
  HandleScope scope(isolate_);
  ExistingCodeLogger logger(isolate_, this);
  logger.LogCodeObjects();
  logger.LogCompiledFunctions();
}

void ExternalCodeEventListener::StartListening(
    CodeEventHandler* code_event_handler) {
  if (is_listening_ || code_event_handler == nullptr) {
    return;
  }
  code_event_handler_ = code_event_handler;
  is_listening_ = isolate_->code_event_dispatcher()->AddListener(this);
  if (is_listening_) {
    LogExistingCode();
  }
}

void ExternalCodeEventListener::StopListening() {
  if (!is_listening_) {
    return;
  }

  isolate_->code_event_dispatcher()->RemoveListener(this);
  is_listening_ = false;
}

void ExternalCodeEventListener::CodeCreateEvent(
    CodeEventListener::LogEventsAndTags tag, AbstractCode code,
    const char* comment) {
  CodeEvent code_event;
  code_event.code_start_address =
      static_cast<uintptr_t>(code.InstructionStart());
  code_event.code_size = static_cast<size_t>(code.InstructionSize());
  code_event.function_name = isolate_->factory()->empty_string();
  code_event.script_name = isolate_->factory()->empty_string();
  code_event.script_line = 0;
  code_event.script_column = 0;
  code_event.code_type = GetCodeEventTypeForTag(tag);
  code_event.comment = comment;

  code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
}

void ExternalCodeEventListener::CodeCreateEvent(
    CodeEventListener::LogEventsAndTags tag, AbstractCode code, Name name) {
  Handle<String> name_string =
      Name::ToFunctionName(isolate_, Handle<Name>(name, isolate_))
          .ToHandleChecked();

  CodeEvent code_event;
  code_event.code_start_address =
      static_cast<uintptr_t>(code.InstructionStart());
  code_event.code_size = static_cast<size_t>(code.InstructionSize());
  code_event.function_name = name_string;
  code_event.script_name = isolate_->factory()->empty_string();
  code_event.script_line = 0;
  code_event.script_column = 0;
  code_event.code_type = GetCodeEventTypeForTag(tag);
  code_event.comment = "";

  code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
}

void ExternalCodeEventListener::CodeCreateEvent(
    CodeEventListener::LogEventsAndTags tag, AbstractCode code,
    SharedFunctionInfo shared, Name name) {
  Handle<String> name_string =
      Name::ToFunctionName(isolate_, Handle<Name>(name, isolate_))
          .ToHandleChecked();

  CodeEvent code_event;
  code_event.code_start_address =
      static_cast<uintptr_t>(code.InstructionStart());
  code_event.code_size = static_cast<size_t>(code.InstructionSize());
  code_event.function_name = name_string;
  code_event.script_name = isolate_->factory()->empty_string();
  code_event.script_line = 0;
  code_event.script_column = 0;
  code_event.code_type = GetCodeEventTypeForTag(tag);
  code_event.comment = "";

  code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
}

void ExternalCodeEventListener::CodeCreateEvent(
    CodeEventListener::LogEventsAndTags tag, AbstractCode code,
    SharedFunctionInfo shared, Name source, int line, int column) {
  Handle<String> name_string =
      Name::ToFunctionName(isolate_, Handle<Name>(shared.Name(), isolate_))
          .ToHandleChecked();
  Handle<String> source_string =
      Name::ToFunctionName(isolate_, Handle<Name>(source, isolate_))
          .ToHandleChecked();

  CodeEvent code_event;
  code_event.code_start_address =
      static_cast<uintptr_t>(code.InstructionStart());
  code_event.code_size = static_cast<size_t>(code.InstructionSize());
  code_event.function_name = name_string;
  code_event.script_name = source_string;
  code_event.script_line = line;
  code_event.script_column = column;
  code_event.code_type = GetCodeEventTypeForTag(tag);
  code_event.comment = "";

  code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
}

void ExternalCodeEventListener::CodeCreateEvent(LogEventsAndTags tag,
                                                const wasm::WasmCode* code,
                                                wasm::WasmName name) {
  // TODO(mmarchini): handle later
}

void ExternalCodeEventListener::RegExpCodeCreateEvent(AbstractCode code,
                                                      String source) {
  CodeEvent code_event;
  code_event.code_start_address =
      static_cast<uintptr_t>(code.InstructionStart());
  code_event.code_size = static_cast<size_t>(code.InstructionSize());
  code_event.function_name = Handle<String>(source, isolate_);
  code_event.script_name = isolate_->factory()->empty_string();
  code_event.script_line = 0;
  code_event.script_column = 0;
  code_event.code_type = GetCodeEventTypeForTag(CodeEventListener::REG_EXP_TAG);
  code_event.comment = "";

  code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event));
}

// Low-level logging support.
class LowLevelLogger : public CodeEventLogger {
 public:
  LowLevelLogger(Isolate* isolate, const char* file_name);
  ~LowLevelLogger() override;

  void CodeMoveEvent(AbstractCode from, AbstractCode to) override;
  void CodeDisableOptEvent(AbstractCode code,
                           SharedFunctionInfo shared) override {}
  void SnapshotPositionEvent(HeapObject obj, int pos);
  void CodeMovingGCEvent() override;

 private:
  void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
                         const char* name, int length) override;
  void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
                         int length) override;

  // Low-level profiling event structures.
  struct CodeCreateStruct {
    static const char kTag = 'C';

    int32_t name_size;
    Address code_address;
    int32_t code_size;
  };

  struct CodeMoveStruct {
    static const char kTag = 'M';

    Address from_address;
    Address to_address;
  };

  static const char kCodeMovingGCTag = 'G';

  // Extension added to V8 log file name to get the low-level log name.
  static const char kLogExt[];

  void LogCodeInfo();
  void LogWriteBytes(const char* bytes, int size);

  template <typename T>
  void LogWriteStruct(const T& s) {
    char tag = T::kTag;
    LogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
    LogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
  }

  FILE* ll_output_handle_;
};

const char LowLevelLogger::kLogExt[] = ".ll";

LowLevelLogger::LowLevelLogger(Isolate* isolate, const char* name)
    : CodeEventLogger(isolate), ll_output_handle_(nullptr) {
  // Open the low-level log file.
  size_t len = strlen(name);
  ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLogExt)));
  MemCopy(ll_name.begin(), name, len);
  MemCopy(ll_name.begin() + len, kLogExt, sizeof(kLogExt));
#if !defined(V8_OS_STARBOARD)
  ll_output_handle_ =
      base::OS::FOpen(ll_name.begin(), base::OS::LogFileOpenMode);
  setvbuf(ll_output_handle_, nullptr, _IOLBF, 0);
#else
  SB_NOTIMPLEMENTED();
#endif

  LogCodeInfo();
}

LowLevelLogger::~LowLevelLogger() {
#if !defined(V8_OS_STARBOARD)
  fclose(ll_output_handle_);
  ll_output_handle_ = nullptr;
#endif
}

void LowLevelLogger::LogCodeInfo() {
#if V8_TARGET_ARCH_IA32
  const char arch[] = "ia32";
#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
  const char arch[] = "x64";
#elif V8_TARGET_ARCH_ARM
  const char arch[] = "arm";
#elif V8_TARGET_ARCH_PPC
  const char arch[] = "ppc";
#elif V8_TARGET_ARCH_MIPS
  const char arch[] = "mips";
#elif V8_TARGET_ARCH_ARM64
  const char arch[] = "arm64";
#elif V8_TARGET_ARCH_S390
  const char arch[] = "s390";
#else
  const char arch[] = "unknown";
#endif
  LogWriteBytes(arch, sizeof(arch));
}

void LowLevelLogger::LogRecordedBuffer(AbstractCode code, SharedFunctionInfo,
                                       const char* name, int length) {
  CodeCreateStruct event;
  event.name_size = length;
  event.code_address = code.InstructionStart();
  event.code_size = code.InstructionSize();
  LogWriteStruct(event);
  LogWriteBytes(name, length);
  LogWriteBytes(reinterpret_cast<const char*>(code.InstructionStart()),
                code.InstructionSize());
}

void LowLevelLogger::LogRecordedBuffer(const wasm::WasmCode* code,
                                       const char* name, int length) {
  CodeCreateStruct event;
  event.name_size = length;
  event.code_address = code->instruction_start();
  event.code_size = code->instructions().length();
  LogWriteStruct(event);
  LogWriteBytes(name, length);
  LogWriteBytes(reinterpret_cast<const char*>(code->instruction_start()),
                code->instructions().length());
}

void LowLevelLogger::CodeMoveEvent(AbstractCode from, AbstractCode to) {
  CodeMoveStruct event;
  event.from_address = from.InstructionStart();
  event.to_address = to.InstructionStart();
  LogWriteStruct(event);
}

void LowLevelLogger::LogWriteBytes(const char* bytes, int size) {
  size_t rv = fwrite(bytes, 1, size, ll_output_handle_);
  DCHECK(static_cast<size_t>(size) == rv);
  USE(rv);
}

void LowLevelLogger::CodeMovingGCEvent() {
  const char tag = kCodeMovingGCTag;

  LogWriteBytes(&tag, sizeof(tag));
}

class JitLogger : public CodeEventLogger {
 public:
  JitLogger(Isolate* isolate, JitCodeEventHandler code_event_handler);

  void CodeMoveEvent(AbstractCode from, AbstractCode to) override;
  void CodeDisableOptEvent(AbstractCode code,
                           SharedFunctionInfo shared) override {}
  void AddCodeLinePosInfoEvent(void* jit_handler_data, int pc_offset,
                               int position,
                               JitCodeEvent::PositionType position_type);

  void* StartCodePosInfoEvent();
  void EndCodePosInfoEvent(Address start_address, void* jit_handler_data);

 private:
  void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
                         const char* name, int length) override;
  void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
                         int length) override;

  JitCodeEventHandler code_event_handler_;
  base::Mutex logger_mutex_;
};

JitLogger::JitLogger(Isolate* isolate, JitCodeEventHandler code_event_handler)
    : CodeEventLogger(isolate), code_event_handler_(code_event_handler) {}

void JitLogger::LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
                                  const char* name, int length) {
  JitCodeEvent event;
  memset(static_cast<void*>(&event), 0, sizeof(event));
  event.type = JitCodeEvent::CODE_ADDED;
  event.code_start = reinterpret_cast<void*>(code.InstructionStart());
  event.code_type =
      code.IsCode() ? JitCodeEvent::JIT_CODE : JitCodeEvent::BYTE_CODE;
  event.code_len = code.InstructionSize();
  Handle<SharedFunctionInfo> shared_function_handle;
  if (!shared.is_null() && shared.script().IsScript()) {
    shared_function_handle =
        Handle<SharedFunctionInfo>(shared, shared.GetIsolate());
  }
  event.script = ToApiHandle<v8::UnboundScript>(shared_function_handle);
  event.name.str = name;
  event.name.len = length;
  event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);
  code_event_handler_(&event);
}

void JitLogger::LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
                                  int length) {
  JitCodeEvent event;
  memset(static_cast<void*>(&event), 0, sizeof(event));
  event.type = JitCodeEvent::CODE_ADDED;
  event.code_type = JitCodeEvent::JIT_CODE;
  event.code_start = code->instructions().begin();
  event.code_len = code->instructions().length();
  event.name.str = name;
  event.name.len = length;
  event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);
  code_event_handler_(&event);
}

void JitLogger::CodeMoveEvent(AbstractCode from, AbstractCode to) {
  base::MutexGuard guard(&logger_mutex_);

  JitCodeEvent event;
  event.type = JitCodeEvent::CODE_MOVED;
  event.code_type =
      from.IsCode() ? JitCodeEvent::JIT_CODE : JitCodeEvent::BYTE_CODE;
  event.code_start = reinterpret_cast<void*>(from.InstructionStart());
  event.code_len = from.InstructionSize();
  event.new_code_start = reinterpret_cast<void*>(to.InstructionStart());
  event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);

  code_event_handler_(&event);
}

void JitLogger::AddCodeLinePosInfoEvent(
    void* jit_handler_data, int pc_offset, int position,
    JitCodeEvent::PositionType position_type) {
  JitCodeEvent event;
  memset(static_cast<void*>(&event), 0, sizeof(event));
  event.type = JitCodeEvent::CODE_ADD_LINE_POS_INFO;
  event.user_data = jit_handler_data;
  event.line_info.offset = pc_offset;
  event.line_info.pos = position;
  event.line_info.position_type = position_type;
  event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);

  code_event_handler_(&event);
}

void* JitLogger::StartCodePosInfoEvent() {
  JitCodeEvent event;
  memset(static_cast<void*>(&event), 0, sizeof(event));
  event.type = JitCodeEvent::CODE_START_LINE_INFO_RECORDING;
  event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);

  code_event_handler_(&event);
  return event.user_data;
}

void JitLogger::EndCodePosInfoEvent(Address start_address,
                                    void* jit_handler_data) {
  JitCodeEvent event;
  memset(static_cast<void*>(&event), 0, sizeof(event));
  event.type = JitCodeEvent::CODE_END_LINE_INFO_RECORDING;
  event.code_start = reinterpret_cast<void*>(start_address);
  event.user_data = jit_handler_data;
  event.isolate = reinterpret_cast<v8::Isolate*>(isolate_);

  code_event_handler_(&event);
}

// TODO(lpy): Keeping sampling thread inside V8 is a workaround currently,
// the reason is to reduce code duplication during migration to sampler library,
// sampling thread, as well as the sampler, will be moved to D8 eventually.
class SamplingThread : public base::Thread {
 public:
  static const int kSamplingThreadStackSize = 64 * KB;

  SamplingThread(sampler::Sampler* sampler, int interval_microseconds)
      : base::Thread(
            base::Thread::Options("SamplingThread", kSamplingThreadStackSize)),
        sampler_(sampler),
        interval_microseconds_(interval_microseconds) {}
  void Run() override {
    while (sampler_->IsActive()) {
      sampler_->DoSample();
      base::OS::Sleep(
          base::TimeDelta::FromMicroseconds(interval_microseconds_));
    }
  }

 private:
  sampler::Sampler* sampler_;
  const int interval_microseconds_;
};

// The Profiler samples pc and sp values for the main thread.
// Each sample is appended to a circular buffer.
// An independent thread removes data and writes it to the log.
// This design minimizes the time spent in the sampler.
//
class Profiler : public base::Thread {
 public:
  explicit Profiler(Isolate* isolate);
  void Engage();
  void Disengage();

  // Inserts collected profiling data into buffer.
  void Insert(v8::TickSample* sample) {
    if (Succ(head_) == static_cast<int>(base::Relaxed_Load(&tail_))) {
      overflow_ = true;
    } else {
      buffer_[head_] = *sample;
      head_ = Succ(head_);
      buffer_semaphore_.Signal();  // Tell we have an element.
    }
  }

  void Run() override;

 private:
  // Waits for a signal and removes profiling data.
  bool Remove(v8::TickSample* sample) {
    buffer_semaphore_.Wait();  // Wait for an element.
    *sample = buffer_[base::Relaxed_Load(&tail_)];
    bool result = overflow_;
    base::Relaxed_Store(
        &tail_, static_cast<base::Atomic32>(Succ(base::Relaxed_Load(&tail_))));
    overflow_ = false;
    return result;
  }

  // Returns the next index in the cyclic buffer.
  int Succ(int index) { return (index + 1) % kBufferSize; }

  Isolate* isolate_;
  // Cyclic buffer for communicating profiling samples
  // between the signal handler and the worker thread.
  static const int kBufferSize = 128;
  v8::TickSample buffer_[kBufferSize];  // Buffer storage.
  int head_;                            // Index to the buffer head.
  base::Atomic32 tail_;                 // Index to the buffer tail.
  bool overflow_;  // Tell whether a buffer overflow has occurred.
  // Semaphore used for buffer synchronization.
  base::Semaphore buffer_semaphore_;

  // Tells whether worker thread should continue running.
  base::Atomic32 running_;
};

//
// Ticker used to provide ticks to the profiler and the sliding state
// window.
//
class Ticker : public sampler::Sampler {
 public:
  Ticker(Isolate* isolate, int interval_microseconds)
      : sampler::Sampler(reinterpret_cast<v8::Isolate*>(isolate)),
        sampling_thread_(
            base::make_unique<SamplingThread>(this, interval_microseconds)) {}

  ~Ticker() override {
    if (IsActive()) Stop();
  }

  void SetProfiler(Profiler* profiler) {
    DCHECK_NULL(profiler_);
    profiler_ = profiler;
    if (!IsActive()) Start();
    sampling_thread_->StartSynchronously();
  }

  void ClearProfiler() {
    profiler_ = nullptr;
    if (IsActive()) Stop();
    sampling_thread_->Join();
  }

  void SampleStack(const v8::RegisterState& state) override {
    if (!profiler_) return;
    Isolate* isolate = reinterpret_cast<Isolate*>(this->isolate());
    TickSample sample;
    sample.Init(isolate, state, TickSample::kIncludeCEntryFrame, true);
    profiler_->Insert(&sample);
  }

 private:
  Profiler* profiler_ = nullptr;
  std::unique_ptr<SamplingThread> sampling_thread_;
};

//
// Profiler implementation when invoking with --prof.
//
Profiler::Profiler(Isolate* isolate)
    : base::Thread(Options("v8:Profiler")),
      isolate_(isolate),
      head_(0),
      overflow_(false),
      buffer_semaphore_(0) {
  base::Relaxed_Store(&tail_, 0);
  base::Relaxed_Store(&running_, 0);
}

void Profiler::Engage() {
  std::vector<base::OS::SharedLibraryAddress> addresses =
      base::OS::GetSharedLibraryAddresses();
  for (const auto& address : addresses) {
    LOG(isolate_, SharedLibraryEvent(address.library_path, address.start,
                                     address.end, address.aslr_slide));
  }

  // Start thread processing the profiler buffer.
  base::Relaxed_Store(&running_, 1);
  Start();

  // Register to get ticks.
  Logger* logger = isolate_->logger();
  logger->ticker_->SetProfiler(this);

  logger->ProfilerBeginEvent();
}

void Profiler::Disengage() {
  // Stop receiving ticks.
  isolate_->logger()->ticker_->ClearProfiler();

  // Terminate the worker thread by setting running_ to false,
  // inserting a fake element in the queue and then wait for
  // the thread to terminate.
  base::Relaxed_Store(&running_, 0);
  v8::TickSample sample;
  Insert(&sample);
  Join();

  LOG(isolate_, UncheckedStringEvent("profiler", "end"));
}

void Profiler::Run() {
  v8::TickSample sample;
  bool overflow = Remove(&sample);
  while (base::Relaxed_Load(&running_)) {
    LOG(isolate_, TickEvent(&sample, overflow));
    overflow = Remove(&sample);
  }
}

//
// Logger class implementation.
//

Logger::Logger(Isolate* isolate)
    : isolate_(isolate),
      log_events_(nullptr),
      is_logging_(false),
      log_(nullptr),
      is_initialized_(false),
      existing_code_logger_(isolate) {}

Logger::~Logger() { delete log_; }

const LogSeparator Logger::kNext = LogSeparator::kSeparator;

void Logger::AddCodeEventListener(CodeEventListener* listener) {
  bool result = isolate_->code_event_dispatcher()->AddListener(listener);
  CHECK(result);
}

void Logger::RemoveCodeEventListener(CodeEventListener* listener) {
  isolate_->code_event_dispatcher()->RemoveListener(listener);
}

void Logger::ProfilerBeginEvent() {
  if (!log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  msg << "profiler" << kNext << "begin" << kNext << FLAG_prof_sampling_interval;
  msg.WriteToLogFile();
}

void Logger::StringEvent(const char* name, const char* value) {
  if (FLAG_log) UncheckedStringEvent(name, value);
}

void Logger::UncheckedStringEvent(const char* name, const char* value) {
  if (!log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  msg << name << kNext << value;
  msg.WriteToLogFile();
}

void Logger::IntPtrTEvent(const char* name, intptr_t value) {
  if (FLAG_log) UncheckedIntPtrTEvent(name, value);
}

void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
  if (!log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  msg << name << kNext;
  msg.AppendFormatString("%" V8PRIdPTR, value);
  msg.WriteToLogFile();
}

void Logger::HandleEvent(const char* name, Address* location) {
  if (!log_->IsEnabled() || !FLAG_log_handles) return;
  Log::MessageBuilder msg(log_);
  msg << name << kNext << reinterpret_cast<void*>(location);
  msg.WriteToLogFile();
}

void Logger::ApiSecurityCheck() {
  if (!log_->IsEnabled() || !FLAG_log_api) return;
  Log::MessageBuilder msg(log_);
  msg << "api" << kNext << "check-security";
  msg.WriteToLogFile();
}

void Logger::SharedLibraryEvent(const std::string& library_path,
                                uintptr_t start, uintptr_t end,
                                intptr_t aslr_slide) {
  if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
  Log::MessageBuilder msg(log_);
  msg << "shared-library" << kNext << library_path.c_str() << kNext
      << reinterpret_cast<void*>(start) << kNext << reinterpret_cast<void*>(end)
      << kNext << aslr_slide;
  msg.WriteToLogFile();
}

void Logger::CodeDeoptEvent(Code code, DeoptimizeKind kind, Address pc,
                            int fp_to_sp_delta) {
  if (!log_->IsEnabled()) return;
  Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(code, pc);
  Log::MessageBuilder msg(log_);
  msg << "code-deopt" << kNext << timer_.Elapsed().InMicroseconds() << kNext
      << code.CodeSize() << kNext
      << reinterpret_cast<void*>(code.InstructionStart());

  // Deoptimization position.
  std::ostringstream deopt_location;
  int inlining_id = -1;
  int script_offset = -1;
  if (info.position.IsKnown()) {
    info.position.Print(deopt_location, code);
    inlining_id = info.position.InliningId();
    script_offset = info.position.ScriptOffset();
  } else {
    deopt_location << "<unknown>";
  }
  msg << kNext << inlining_id << kNext << script_offset << kNext;
  msg << Deoptimizer::MessageFor(kind) << kNext;
  msg << deopt_location.str().c_str() << kNext
      << DeoptimizeReasonToString(info.deopt_reason);
  msg.WriteToLogFile();
}

void Logger::CurrentTimeEvent() {
  if (!log_->IsEnabled()) return;
  DCHECK(FLAG_log_internal_timer_events);
  Log::MessageBuilder msg(log_);
  msg << "current-time" << kNext << timer_.Elapsed().InMicroseconds();
  msg.WriteToLogFile();
}

void Logger::TimerEvent(Logger::StartEnd se, const char* name) {
  if (!log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  switch (se) {
    case START:
      msg << "timer-event-start";
      break;
    case END:
      msg << "timer-event-end";
      break;
    case STAMP:
      msg << "timer-event";
  }
  msg << kNext << name << kNext << timer_.Elapsed().InMicroseconds();
  msg.WriteToLogFile();
}

bool Logger::is_logging() {
  // Disable logging while the CPU profiler is running.
  if (isolate_->is_profiling()) return false;
  return is_logging_;
}

// Instantiate template methods.
#define V(TimerName, expose)                                           \
  template void TimerEventScope<TimerEvent##TimerName>::LogTimerEvent( \
      Logger::StartEnd se);
TIMER_EVENTS_LIST(V)
#undef V

void Logger::ApiNamedPropertyAccess(const char* tag, JSObject holder,
                                    Object property_name) {
  DCHECK(property_name.IsName());
  if (!log_->IsEnabled() || !FLAG_log_api) return;
  Log::MessageBuilder msg(log_);
  msg << "api" << kNext << tag << kNext << holder.class_name() << kNext
      << Name::cast(property_name);
  msg.WriteToLogFile();
}

void Logger::ApiIndexedPropertyAccess(const char* tag, JSObject holder,
                                      uint32_t index) {
  if (!log_->IsEnabled() || !FLAG_log_api) return;
  Log::MessageBuilder msg(log_);
  msg << "api" << kNext << tag << kNext << holder.class_name() << kNext
      << index;
  msg.WriteToLogFile();
}

void Logger::ApiObjectAccess(const char* tag, JSObject object) {
  if (!log_->IsEnabled() || !FLAG_log_api) return;
  Log::MessageBuilder msg(log_);
  msg << "api" << kNext << tag << kNext << object.class_name();
  msg.WriteToLogFile();
}

void Logger::ApiEntryCall(const char* name) {
  if (!log_->IsEnabled() || !FLAG_log_api) return;
  Log::MessageBuilder msg(log_);
  msg << "api" << kNext << name;
  msg.WriteToLogFile();
}

void Logger::NewEvent(const char* name, void* object, size_t size) {
  if (!log_->IsEnabled() || !FLAG_log) return;
  Log::MessageBuilder msg(log_);
  msg << "new" << kNext << name << kNext << object << kNext
      << static_cast<unsigned int>(size);
  msg.WriteToLogFile();
}

void Logger::DeleteEvent(const char* name, void* object) {
  if (!log_->IsEnabled() || !FLAG_log) return;
  Log::MessageBuilder msg(log_);
  msg << "delete" << kNext << name << kNext << object;
  msg.WriteToLogFile();
}

void Logger::CallbackEventInternal(const char* prefix, Name name,
                                   Address entry_point) {
  if (!FLAG_log_code || !log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  msg << kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT] << kNext
      << kLogEventsNames[CodeEventListener::CALLBACK_TAG] << kNext << -2
      << kNext << timer_.Elapsed().InMicroseconds() << kNext
      << reinterpret_cast<void*>(entry_point) << kNext << 1 << kNext << prefix
      << name;
  msg.WriteToLogFile();
}

void Logger::CallbackEvent(Name name, Address entry_point) {
  CallbackEventInternal("", name, entry_point);
}

void Logger::GetterCallbackEvent(Name name, Address entry_point) {
  CallbackEventInternal("get ", name, entry_point);
}

void Logger::SetterCallbackEvent(Name name, Address entry_point) {
  CallbackEventInternal("set ", name, entry_point);
}

namespace {

void AppendCodeCreateHeader(
    Log::MessageBuilder& msg,  // NOLINT(runtime/references)
    CodeEventListener::LogEventsAndTags tag, AbstractCode::Kind kind,
    uint8_t* address, int size, base::ElapsedTimer* timer) {
  msg << kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT]
      << Logger::kNext << kLogEventsNames[tag] << Logger::kNext << kind
      << Logger::kNext << timer->Elapsed().InMicroseconds() << Logger::kNext
      << reinterpret_cast<void*>(address) << Logger::kNext << size
      << Logger::kNext;
}

void AppendCodeCreateHeader(
    Log::MessageBuilder& msg,  // NOLINT(runtime/references)
    CodeEventListener::LogEventsAndTags tag, AbstractCode code,
    base::ElapsedTimer* timer) {
  AppendCodeCreateHeader(msg, tag, code.kind(),
                         reinterpret_cast<uint8_t*>(code.InstructionStart()),
                         code.InstructionSize(), timer);
}

}  // namespace

void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                             AbstractCode code, const char* comment) {
  if (!is_listening_to_code_events()) return;
  if (!FLAG_log_code || !log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  AppendCodeCreateHeader(msg, tag, code, &timer_);
  msg << comment;
  msg.WriteToLogFile();
}

void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                             AbstractCode code, Name name) {
  if (!is_listening_to_code_events()) return;
  if (!FLAG_log_code || !log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  AppendCodeCreateHeader(msg, tag, code, &timer_);
  msg << name;
  msg.WriteToLogFile();
}

void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                             AbstractCode code, SharedFunctionInfo shared,
                             Name name) {
  if (!is_listening_to_code_events()) return;
  if (!FLAG_log_code || !log_->IsEnabled()) return;
  if (code == AbstractCode::cast(
                  isolate_->builtins()->builtin(Builtins::kCompileLazy))) {
    return;
  }

  Log::MessageBuilder msg(log_);
  AppendCodeCreateHeader(msg, tag, code, &timer_);
  msg << name << kNext << reinterpret_cast<void*>(shared.address()) << kNext
      << ComputeMarker(shared, code);
  msg.WriteToLogFile();
}

void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                             const wasm::WasmCode* code, wasm::WasmName name) {
  if (!is_listening_to_code_events()) return;
  if (!FLAG_log_code || !log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  AppendCodeCreateHeader(msg, tag, AbstractCode::Kind::WASM_FUNCTION,
                         code->instructions().begin(),
                         code->instructions().length(), &timer_);
  if (name.empty()) {
    msg << "<unknown wasm>";
  } else {
    msg.AppendString(name);
  }
  // We have to add two extra fields that allow the tick processor to group
  // events for the same wasm function, even if it gets compiled again. For
  // normal JS functions, we use the shared function info. For wasm, the pointer
  // to the native module + function index works well enough.
  // TODO(herhut) Clean up the tick processor code instead.
  void* tag_ptr =
      reinterpret_cast<byte*>(code->native_module()) + code->index();
  msg << kNext << tag_ptr << kNext << ComputeMarker(code);
  msg.WriteToLogFile();
}

// Although, it is possible to extract source and line from
// the SharedFunctionInfo object, we left it to caller
// to leave logging functions free from heap allocations.
void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                             AbstractCode code, SharedFunctionInfo shared,
                             Name source, int line, int column) {
  if (!is_listening_to_code_events()) return;
  if (!FLAG_log_code || !log_->IsEnabled()) return;
  {
    Log::MessageBuilder msg(log_);
    AppendCodeCreateHeader(msg, tag, code, &timer_);
    msg << shared.DebugName() << " " << source << ":" << line << ":" << column
        << kNext << reinterpret_cast<void*>(shared.address()) << kNext
        << ComputeMarker(shared, code);
    msg.WriteToLogFile();
  }

  if (!FLAG_log_source_code) return;
  Object script_object = shared.script();
  if (!script_object.IsScript()) return;
  Script script = Script::cast(script_object);
  if (!EnsureLogScriptSource(script)) return;

  // We log source code information in the form:
  //
  // code-source-info <addr>,<script>,<start>,<end>,<pos>,<inline-pos>,<fns>
  //
  // where
  //   <addr> is code object address
  //   <script> is script id
  //   <start> is the starting position inside the script
  //   <end> is the end position inside the script
  //   <pos> is source position table encoded in the string,
  //      it is a sequence of C<code-offset>O<script-offset>[I<inlining-id>]
  //      where
  //        <code-offset> is the offset within the code object
  //        <script-offset> is the position within the script
  //        <inlining-id> is the offset in the <inlining> table
  //   <inlining> table is a sequence of strings of the form
  //      F<function-id>O<script-offset>[I<inlining-id>]
  //      where
  //         <function-id> is an index into the <fns> function table
  //   <fns> is the function table encoded as a sequence of strings
  //      S<shared-function-info-address>
  Log::MessageBuilder msg(log_);
  msg << "code-source-info" << kNext
      << reinterpret_cast<void*>(code.InstructionStart()) << kNext
      << script.id() << kNext << shared.StartPosition() << kNext
      << shared.EndPosition() << kNext;

  SourcePositionTableIterator iterator(code.source_position_table());
  bool hasInlined = false;
  for (; !iterator.done(); iterator.Advance()) {
    SourcePosition pos = iterator.source_position();
    msg << "C" << iterator.code_offset() << "O" << pos.ScriptOffset();
    if (pos.isInlined()) {
      msg << "I" << pos.InliningId();
      hasInlined = true;
    }
  }
  msg << kNext;
  int maxInlinedId = -1;
  if (hasInlined) {
    PodArray<InliningPosition> inlining_positions =
        DeoptimizationData::cast(Code::cast(code).deoptimization_data())
            .InliningPositions();
    for (int i = 0; i < inlining_positions.length(); i++) {
      InliningPosition inlining_pos = inlining_positions.get(i);
      msg << "F";
      if (inlining_pos.inlined_function_id != -1) {
        msg << inlining_pos.inlined_function_id;
        if (inlining_pos.inlined_function_id > maxInlinedId) {
          maxInlinedId = inlining_pos.inlined_function_id;
        }
      }
      SourcePosition pos = inlining_pos.position;
      msg << "O" << pos.ScriptOffset();
      if (pos.isInlined()) {
        msg << "I" << pos.InliningId();
      }
    }
  }
  msg << kNext;
  if (hasInlined) {
    DeoptimizationData deopt_data =
        DeoptimizationData::cast(Code::cast(code).deoptimization_data());

    msg << std::hex;
    for (int i = 0; i <= maxInlinedId; i++) {
      msg << "S"
          << reinterpret_cast<void*>(
                 deopt_data.GetInlinedFunction(i).address());
    }
    msg << std::dec;
  }
  msg.WriteToLogFile();
}

void Logger::CodeDisableOptEvent(AbstractCode code, SharedFunctionInfo shared) {
  if (!is_listening_to_code_events()) return;
  if (!FLAG_log_code || !log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  msg << kLogEventsNames[CodeEventListener::CODE_DISABLE_OPT_EVENT] << kNext
      << shared.DebugName() << kNext
      << GetBailoutReason(shared.disable_optimization_reason());
  msg.WriteToLogFile();
}

void Logger::CodeMovingGCEvent() {
  if (!is_listening_to_code_events()) return;
  if (!log_->IsEnabled() || !FLAG_ll_prof) return;
  base::OS::SignalCodeMovingGC();
}

void Logger::RegExpCodeCreateEvent(AbstractCode code, String source) {
  if (!is_listening_to_code_events()) return;
  if (!FLAG_log_code || !log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  AppendCodeCreateHeader(msg, CodeEventListener::REG_EXP_TAG, code, &timer_);
  msg << source;
  msg.WriteToLogFile();
}

void Logger::CodeMoveEvent(AbstractCode from, AbstractCode to) {
  if (!is_listening_to_code_events()) return;
  MoveEventInternal(CodeEventListener::CODE_MOVE_EVENT, from.address(),
                    to.address());
}

namespace {

void CodeLinePosEvent(
    JitLogger* jit_logger, Address code_start,
    SourcePositionTableIterator& iter) {  // NOLINT(runtime/references)
  if (jit_logger) {
    void* jit_handler_data = jit_logger->StartCodePosInfoEvent();
    for (; !iter.done(); iter.Advance()) {
      if (iter.is_statement()) {
        jit_logger->AddCodeLinePosInfoEvent(
            jit_handler_data, iter.code_offset(),
            iter.source_position().ScriptOffset(),
            JitCodeEvent::STATEMENT_POSITION);
      }
      jit_logger->AddCodeLinePosInfoEvent(jit_handler_data, iter.code_offset(),
                                          iter.source_position().ScriptOffset(),
                                          JitCodeEvent::POSITION);
    }
    jit_logger->EndCodePosInfoEvent(code_start, jit_handler_data);
  }
}

}  // namespace

void Logger::CodeLinePosInfoRecordEvent(Address code_start,
                                        ByteArray source_position_table) {
  SourcePositionTableIterator iter(source_position_table);
  CodeLinePosEvent(jit_logger_.get(), code_start, iter);
}

void Logger::CodeLinePosInfoRecordEvent(
    Address code_start, Vector<const byte> source_position_table) {
  SourcePositionTableIterator iter(source_position_table);
  CodeLinePosEvent(jit_logger_.get(), code_start, iter);
}

void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
  if (code_name == nullptr) return;  // Not a code object.
  Log::MessageBuilder msg(log_);
  msg << kLogEventsNames[CodeEventListener::SNAPSHOT_CODE_NAME_EVENT] << kNext
      << pos << kNext << code_name;
  msg.WriteToLogFile();
}

void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
  if (!is_listening_to_code_events()) return;
  MoveEventInternal(CodeEventListener::SHARED_FUNC_MOVE_EVENT, from, to);
}

void Logger::MoveEventInternal(CodeEventListener::LogEventsAndTags event,
                               Address from, Address to) {
  if (!FLAG_log_code || !log_->IsEnabled()) return;
  Log::MessageBuilder msg(log_);
  msg << kLogEventsNames[event] << kNext << reinterpret_cast<void*>(from)
      << kNext << reinterpret_cast<void*>(to);
  msg.WriteToLogFile();
}

void Logger::ResourceEvent(const char* name, const char* tag) {
  if (!log_->IsEnabled() || !FLAG_log) return;
  Log::MessageBuilder msg(log_);
  msg << name << kNext << tag << kNext;

  uint32_t sec, usec;
  if (base::OS::GetUserTime(&sec, &usec) != -1) {
    msg << sec << kNext << usec << kNext;
  }
  msg.AppendFormatString("%.0f",
                         V8::GetCurrentPlatform()->CurrentClockTimeMillis());
  msg.WriteToLogFile();
}

void Logger::SuspectReadEvent(Name name, Object obj) {
  if (!log_->IsEnabled() || !FLAG_log_suspect) return;
  Log::MessageBuilder msg(log_);
  String class_name = obj.IsJSObject() ? JSObject::cast(obj).class_name()
                                       : ReadOnlyRoots(isolate_).empty_string();
  msg << "suspect-read" << kNext << class_name << kNext << name;
  msg.WriteToLogFile();
}

namespace {
void AppendFunctionMessage(
    Log::MessageBuilder& msg,  // NOLINT(runtime/references)
    const char* reason, int script_id, double time_delta, int start_position,
    int end_position, base::ElapsedTimer* timer) {
  msg << "function" << Logger::kNext << reason << Logger::kNext << script_id
      << Logger::kNext << start_position << Logger::kNext << end_position
      << Logger::kNext << time_delta << Logger::kNext
      << timer->Elapsed().InMicroseconds() << Logger::kNext;
}
}  // namespace

void Logger::FunctionEvent(const char* reason, int script_id, double time_delta,
                           int start_position, int end_position,
                           String function_name) {
  if (!log_->IsEnabled() || !FLAG_log_function_events) return;
  Log::MessageBuilder msg(log_);
  AppendFunctionMessage(msg, reason, script_id, time_delta, start_position,
                        end_position, &timer_);
  if (!function_name.is_null()) msg << function_name;
  msg.WriteToLogFile();
}

void Logger::FunctionEvent(const char* reason, int script_id, double time_delta,
                           int start_position, int end_position,
                           const char* function_name,
                           size_t function_name_length) {
  if (!log_->IsEnabled() || !FLAG_log_function_events) return;
  Log::MessageBuilder msg(log_);
  AppendFunctionMessage(msg, reason, script_id, time_delta, start_position,
                        end_position, &timer_);
  if (function_name_length > 0) {
    msg.AppendString(function_name, function_name_length);
  }
  msg.WriteToLogFile();
}

void Logger::CompilationCacheEvent(const char* action, const char* cache_type,
                                   SharedFunctionInfo sfi) {
  if (!log_->IsEnabled() || !FLAG_log_function_events) return;
  Log::MessageBuilder msg(log_);
  int script_id = -1;
  if (sfi.script().IsScript()) {
    script_id = Script::cast(sfi.script()).id();
  }
  msg << "compilation-cache" << Logger::kNext << action << Logger::kNext
      << cache_type << Logger::kNext << script_id << Logger::kNext
      << sfi.StartPosition() << Logger::kNext << sfi.EndPosition()
      << Logger::kNext << timer_.Elapsed().InMicroseconds();
  msg.WriteToLogFile();
}

void Logger::ScriptEvent(ScriptEventType type, int script_id) {
  if (!log_->IsEnabled() || !FLAG_log_function_events) return;
  Log::MessageBuilder msg(log_);
  msg << "script" << Logger::kNext;
  switch (type) {
    case ScriptEventType::kReserveId:
      msg << "reserve-id";
      break;
    case ScriptEventType::kCreate:
      msg << "create";
      break;
    case ScriptEventType::kDeserialize:
      msg << "deserialize";
      break;
    case ScriptEventType::kBackgroundCompile:
      msg << "background-compile";
      break;
    case ScriptEventType::kStreamingCompile:
      msg << "streaming-compile";
      break;
  }
  msg << Logger::kNext << script_id << Logger::kNext
      << timer_.Elapsed().InMicroseconds();
  msg.WriteToLogFile();
}

void Logger::ScriptDetails(Script script) {
  if (!log_->IsEnabled() || !FLAG_log_function_events) return;
  {
    Log::MessageBuilder msg(log_);
    msg << "script-details" << Logger::kNext << script.id() << Logger::kNext;
    if (script.name().IsString()) {
      msg << String::cast(script.name());
    }
    msg << Logger::kNext << script.line_offset() << Logger::kNext
        << script.column_offset() << Logger::kNext;
    if (script.source_mapping_url().IsString()) {
      msg << String::cast(script.source_mapping_url());
    }
    msg.WriteToLogFile();
  }
  EnsureLogScriptSource(script);
}

bool Logger::EnsureLogScriptSource(Script script) {
  if (!log_->IsEnabled()) return false;
  Log::MessageBuilder msg(log_);
  // Make sure the script is written to the log file.
  int script_id = script.id();
  if (logged_source_code_.find(script_id) != logged_source_code_.end()) {
    return true;
  }
  // This script has not been logged yet.
  logged_source_code_.insert(script_id);
  Object source_object = script.source();
  if (!source_object.IsString()) return false;
  String source_code = String::cast(source_object);
  msg << "script-source" << kNext << script_id << kNext;

  // Log the script name.
  if (script.name().IsString()) {
    msg << String::cast(script.name()) << kNext;
  } else {
    msg << "<unknown>" << kNext;
  }

  // Log the source code.
  msg << source_code;
  msg.WriteToLogFile();
  return true;
}

void Logger::RuntimeCallTimerEvent() {
  RuntimeCallStats* stats = isolate_->counters()->runtime_call_stats();
  RuntimeCallCounter* counter = stats->current_counter();
  if (counter == nullptr) return;
  Log::MessageBuilder msg(log_);
  msg << "active-runtime-timer" << kNext << counter->name();
  msg.WriteToLogFile();
}

void Logger::TickEvent(v8::TickSample* sample, bool overflow) {
  if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
  if (V8_UNLIKELY(TracingFlags::runtime_stats.load(std::memory_order_relaxed) ==
                  v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) {
    RuntimeCallTimerEvent();
  }
  Log::MessageBuilder msg(log_);
  msg << kLogEventsNames[CodeEventListener::TICK_EVENT] << kNext
      << reinterpret_cast<void*>(sample->pc) << kNext
      << timer_.Elapsed().InMicroseconds();
  if (sample->has_external_callback) {
    msg << kNext << 1 << kNext
        << reinterpret_cast<void*>(sample->external_callback_entry);
  } else {
    msg << kNext << 0 << kNext << reinterpret_cast<void*>(sample->tos);
  }
  msg << kNext << static_cast<int>(sample->state);
  if (overflow) msg << kNext << "overflow";
  for (unsigned i = 0; i < sample->frames_count; ++i) {
    msg << kNext << reinterpret_cast<void*>(sample->stack[i]);
  }
  msg.WriteToLogFile();
}

void Logger::ICEvent(const char* type, bool keyed, Map map, Object key,
                     char old_state, char new_state, const char* modifier,
                     const char* slow_stub_reason) {
  if (!log_->IsEnabled() || !FLAG_trace_ic) return;
  Log::MessageBuilder msg(log_);
  if (keyed) msg << "Keyed";
  int line;
  int column;
  Address pc = isolate_->GetAbstractPC(&line, &column);
  msg << type << kNext << reinterpret_cast<void*>(pc) << kNext << line << kNext
      << column << kNext << old_state << kNext << new_state << kNext
      << AsHex::Address(map.ptr()) << kNext;
  if (key.IsSmi()) {
    msg << Smi::ToInt(key);
  } else if (key.IsNumber()) {
    msg << key.Number();
  } else if (key.IsName()) {
    msg << Name::cast(key);
  }
  msg << kNext << modifier << kNext;
  if (slow_stub_reason != nullptr) {
    msg << slow_stub_reason;
  }
  msg.WriteToLogFile();
}

void Logger::MapEvent(const char* type, Map from, Map to, const char* reason,
                      HeapObject name_or_sfi) {
  DisallowHeapAllocation no_gc;
  if (!log_->IsEnabled() || !FLAG_trace_maps) return;
  if (!to.is_null()) MapDetails(to);
  int line = -1;
  int column = -1;
  Address pc = 0;

  if (!isolate_->bootstrapper()->IsActive()) {
    pc = isolate_->GetAbstractPC(&line, &column);
  }
  Log::MessageBuilder msg(log_);
  msg << "map" << kNext << type << kNext << timer_.Elapsed().InMicroseconds()
      << kNext << AsHex::Address(from.ptr()) << kNext
      << AsHex::Address(to.ptr()) << kNext << AsHex::Address(pc) << kNext
      << line << kNext << column << kNext << reason << kNext;

  if (!name_or_sfi.is_null()) {
    if (name_or_sfi.IsName()) {
      msg << Name::cast(name_or_sfi);
    } else if (name_or_sfi.IsSharedFunctionInfo()) {
      SharedFunctionInfo sfi = SharedFunctionInfo::cast(name_or_sfi);
      msg << sfi.DebugName();
#if V8_SFI_HAS_UNIQUE_ID
      msg << " " << sfi.unique_id();
#endif  // V8_SFI_HAS_UNIQUE_ID
    }
  }
  msg.WriteToLogFile();
}

void Logger::MapCreate(Map map) {
  if (!log_->IsEnabled() || !FLAG_trace_maps) return;
  DisallowHeapAllocation no_gc;
  Log::MessageBuilder msg(log_);
  msg << "map-create" << kNext << timer_.Elapsed().InMicroseconds() << kNext
      << AsHex::Address(map.ptr());
  msg.WriteToLogFile();
}

void Logger::MapDetails(Map map) {
  if (!log_->IsEnabled() || !FLAG_trace_maps) return;
  DisallowHeapAllocation no_gc;
  Log::MessageBuilder msg(log_);
  msg << "map-details" << kNext << timer_.Elapsed().InMicroseconds() << kNext
      << AsHex::Address(map.ptr()) << kNext;
  if (FLAG_trace_maps_details) {
    std::ostringstream buffer;
    map.PrintMapDetails(buffer);
    msg << buffer.str().c_str();
  }
  msg.WriteToLogFile();
}

static void AddFunctionAndCode(SharedFunctionInfo sfi, AbstractCode code_object,
                               Handle<SharedFunctionInfo>* sfis,
                               Handle<AbstractCode>* code_objects, int offset) {
  if (sfis != nullptr) {
    sfis[offset] = Handle<SharedFunctionInfo>(sfi, sfi.GetIsolate());
  }
  if (code_objects != nullptr) {
    code_objects[offset] = Handle<AbstractCode>(code_object, sfi.GetIsolate());
  }
}

static int EnumerateCompiledFunctions(Heap* heap,
                                      Handle<SharedFunctionInfo>* sfis,
                                      Handle<AbstractCode>* code_objects) {
  HeapObjectIterator iterator(heap);
  DisallowHeapAllocation no_gc;
  int compiled_funcs_count = 0;

  // Iterate the heap to find shared function info objects and record
  // the unoptimized code for them.
  for (HeapObject obj = iterator.Next(); !obj.is_null();
       obj = iterator.Next()) {
    if (obj.IsSharedFunctionInfo()) {
      SharedFunctionInfo sfi = SharedFunctionInfo::cast(obj);
      if (sfi.is_compiled() && (!sfi.script().IsScript() ||
                                Script::cast(sfi.script()).HasValidSource())) {
        AddFunctionAndCode(sfi, AbstractCode::cast(sfi.abstract_code()), sfis,
                           code_objects, compiled_funcs_count);
        ++compiled_funcs_count;
      }
    } else if (obj.IsJSFunction()) {
      // Given that we no longer iterate over all optimized JSFunctions, we need
      // to take care of this here.
      JSFunction function = JSFunction::cast(obj);
      SharedFunctionInfo sfi = SharedFunctionInfo::cast(function.shared());
      Object maybe_script = sfi.script();
      if (maybe_script.IsScript() &&
          !Script::cast(maybe_script).HasValidSource()) {
        continue;
      }
      // TODO(jarin) This leaves out deoptimized code that might still be on the
      // stack. Also note that we will not log optimized code objects that are
      // only on a type feedback vector. We should make this mroe precise.
      if (function.IsOptimized()) {
        AddFunctionAndCode(sfi, AbstractCode::cast(function.code()), sfis,
                           code_objects, compiled_funcs_count);
        ++compiled_funcs_count;
      }
    }
  }
  return compiled_funcs_count;
}

static int EnumerateWasmModuleObjects(
    Heap* heap, Handle<WasmModuleObject>* module_objects) {
  HeapObjectIterator iterator(heap);
  DisallowHeapAllocation no_gc;
  int module_objects_count = 0;

  for (HeapObject obj = iterator.Next(); !obj.is_null();
       obj = iterator.Next()) {
    if (obj.IsWasmModuleObject()) {
      WasmModuleObject module = WasmModuleObject::cast(obj);
      if (module_objects != nullptr) {
        module_objects[module_objects_count] =
            handle(module, Isolate::FromHeap(heap));
      }
      module_objects_count++;
    }
  }
  return module_objects_count;
}

void Logger::LogCodeObject(Object object) {
  existing_code_logger_.LogCodeObject(object);
}

void Logger::LogCodeObjects() { existing_code_logger_.LogCodeObjects(); }

void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
                                 Handle<AbstractCode> code) {
  existing_code_logger_.LogExistingFunction(shared, code);
}

void Logger::LogCompiledFunctions() {
  existing_code_logger_.LogCompiledFunctions();
}

void Logger::LogAccessorCallbacks() {
  Heap* heap = isolate_->heap();
  HeapObjectIterator iterator(heap);
  DisallowHeapAllocation no_gc;
  for (HeapObject obj = iterator.Next(); !obj.is_null();
       obj = iterator.Next()) {
    if (!obj.IsAccessorInfo()) continue;
    AccessorInfo ai = AccessorInfo::cast(obj);
    if (!ai.name().IsName()) continue;
    Address getter_entry = v8::ToCData<Address>(ai.getter());
    Name name = Name::cast(ai.name());
    if (getter_entry != 0) {
#if USES_FUNCTION_DESCRIPTORS
      getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(getter_entry);
#endif
      PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
    }
    Address setter_entry = v8::ToCData<Address>(ai.setter());
    if (setter_entry != 0) {
#if USES_FUNCTION_DESCRIPTORS
      setter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(setter_entry);
#endif
      PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
    }
  }
}

void Logger::LogAllMaps() {
  DisallowHeapAllocation no_gc;
  Heap* heap = isolate_->heap();
  HeapObjectIterator iterator(heap);
  for (HeapObject obj = iterator.Next(); !obj.is_null();
       obj = iterator.Next()) {
    if (!obj.IsMap()) continue;
    Map map = Map::cast(obj);
    MapCreate(map);
    MapDetails(map);
  }
}

static void AddIsolateIdIfNeeded(std::ostream& os,  // NOLINT
                                 Isolate* isolate) {
  if (FLAG_logfile_per_isolate) {
    os << "isolate-" << isolate << "-" << base::OS::GetCurrentProcessId()
       << "-";
  }
}

static void PrepareLogFileName(std::ostream& os,  // NOLINT
                               Isolate* isolate, const char* file_name) {
  int dir_separator_count = 0;
  for (const char* p = file_name; *p; p++) {
    if (base::OS::isDirectorySeparator(*p)) dir_separator_count++;
  }

  for (const char* p = file_name; *p; p++) {
    if (dir_separator_count == 0) {
      AddIsolateIdIfNeeded(os, isolate);
      dir_separator_count--;
    }
    if (*p == '%') {
      p++;
      switch (*p) {
        case '\0':
          // If there's a % at the end of the string we back up
          // one character so we can escape the loop properly.
          p--;
          break;
        case 'p':
          os << base::OS::GetCurrentProcessId();
          break;
        case 't':
          // %t expands to the current time in milliseconds.
          os << static_cast<int64_t>(
              V8::GetCurrentPlatform()->CurrentClockTimeMillis());
          break;
        case '%':
          // %% expands (contracts really) to %.
          os << '%';
          break;
        default:
          // All other %'s expand to themselves.
          os << '%' << *p;
          break;
      }
    } else {
      if (base::OS::isDirectorySeparator(*p)) dir_separator_count--;
      os << *p;
    }
  }
}

bool Logger::SetUp(Isolate* isolate) {
  // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
  if (is_initialized_) return true;
  is_initialized_ = true;

  std::ostringstream log_file_name;
  std::ostringstream source_log_file_name;
  PrepareLogFileName(log_file_name, isolate, FLAG_logfile);
  log_ = new Log(this, log_file_name.str().c_str());

  if (FLAG_perf_basic_prof) {
    perf_basic_logger_.reset(new PerfBasicLogger(isolate));
    AddCodeEventListener(perf_basic_logger_.get());
  }

  if (FLAG_perf_prof) {
    perf_jit_logger_.reset(new PerfJitLogger(isolate));
    AddCodeEventListener(perf_jit_logger_.get());
  }

  if (FLAG_ll_prof) {
    ll_logger_.reset(new LowLevelLogger(isolate, log_file_name.str().c_str()));
    AddCodeEventListener(ll_logger_.get());
  }

  ticker_.reset(new Ticker(isolate, FLAG_prof_sampling_interval));

  if (Log::InitLogAtStart()) {
    is_logging_ = true;
  }

  timer_.Start();

  if (FLAG_prof_cpp) {
    profiler_.reset(new Profiler(isolate));
    is_logging_ = true;
    profiler_->Engage();
  }

  if (is_logging_) {
    AddCodeEventListener(this);
  }

  return true;
}

void Logger::SetCodeEventHandler(uint32_t options,
                                 JitCodeEventHandler event_handler) {
  if (jit_logger_) {
    RemoveCodeEventListener(jit_logger_.get());
    jit_logger_.reset();
  }

  if (event_handler) {
    if (isolate_->wasm_engine() != nullptr) {
      isolate_->wasm_engine()->EnableCodeLogging(isolate_);
    }
    jit_logger_.reset(new JitLogger(isolate_, event_handler));
    AddCodeEventListener(jit_logger_.get());
    if (options & kJitCodeEventEnumExisting) {
      HandleScope scope(isolate_);
      LogCodeObjects();
      LogCompiledFunctions();
    }
  }
}

sampler::Sampler* Logger::sampler() { return ticker_.get(); }

void Logger::StopProfilerThread() {
  if (profiler_ != nullptr) {
    profiler_->Disengage();
    profiler_.reset();
  }
}

FILE* Logger::TearDown() {
  if (!is_initialized_) return nullptr;
  is_initialized_ = false;

  // Stop the profiler thread before closing the file.
  StopProfilerThread();

  ticker_.reset();

  if (perf_basic_logger_) {
    RemoveCodeEventListener(perf_basic_logger_.get());
    perf_basic_logger_.reset();
  }

  if (perf_jit_logger_) {
    RemoveCodeEventListener(perf_jit_logger_.get());
    perf_jit_logger_.reset();
  }

  if (ll_logger_) {
    RemoveCodeEventListener(ll_logger_.get());
    ll_logger_.reset();
  }

  if (jit_logger_) {
    RemoveCodeEventListener(jit_logger_.get());
    jit_logger_.reset();
  }

  return log_->Close();
}

void ExistingCodeLogger::LogCodeObject(Object object) {
  AbstractCode abstract_code = AbstractCode::cast(object);
  CodeEventListener::LogEventsAndTags tag = CodeEventListener::STUB_TAG;
  const char* description = "Unknown code from before profiling";
  switch (abstract_code.kind()) {
    case AbstractCode::INTERPRETED_FUNCTION:
    case AbstractCode::OPTIMIZED_FUNCTION:
      return;  // We log this later using LogCompiledFunctions.
    case AbstractCode::BYTECODE_HANDLER:
      return;  // We log it later by walking the dispatch table.
    case AbstractCode::STUB:
      description = "STUB code";
      tag = CodeEventListener::STUB_TAG;
      break;
    case AbstractCode::REGEXP:
      description = "Regular expression code";
      tag = CodeEventListener::REG_EXP_TAG;
      break;
    case AbstractCode::BUILTIN:
      if (Code::cast(object).is_interpreter_trampoline_builtin() &&
          Code::cast(object) !=
              *BUILTIN_CODE(isolate_, InterpreterEntryTrampoline)) {
        return;
      }
      description =
          isolate_->builtins()->name(abstract_code.GetCode().builtin_index());
      tag = CodeEventListener::BUILTIN_TAG;
      break;
    case AbstractCode::WASM_FUNCTION:
      description = "A Wasm function";
      tag = CodeEventListener::FUNCTION_TAG;
      break;
    case AbstractCode::JS_TO_WASM_FUNCTION:
      description = "A JavaScript to Wasm adapter";
      tag = CodeEventListener::STUB_TAG;
      break;
    case AbstractCode::WASM_TO_CAPI_FUNCTION:
      description = "A Wasm to C-API adapter";
      tag = CodeEventListener::STUB_TAG;
      break;
    case AbstractCode::WASM_TO_JS_FUNCTION:
      description = "A Wasm to JavaScript adapter";
      tag = CodeEventListener::STUB_TAG;
      break;
    case AbstractCode::WASM_INTERPRETER_ENTRY:
      description = "A Wasm to Interpreter adapter";
      tag = CodeEventListener::STUB_TAG;
      break;
    case AbstractCode::C_WASM_ENTRY:
      description = "A C to Wasm entry stub";
      tag = CodeEventListener::STUB_TAG;
      break;
    case AbstractCode::NUMBER_OF_KINDS:
      UNIMPLEMENTED();
  }
  CALL_CODE_EVENT_HANDLER(CodeCreateEvent(tag, abstract_code, description))
}

void ExistingCodeLogger::LogCodeObjects() {
  Heap* heap = isolate_->heap();
  HeapObjectIterator iterator(heap);
  DisallowHeapAllocation no_gc;
  for (HeapObject obj = iterator.Next(); !obj.is_null();
       obj = iterator.Next()) {
    if (obj.IsCode()) LogCodeObject(obj);
    if (obj.IsBytecodeArray()) LogCodeObject(obj);
  }
}

void ExistingCodeLogger::LogCompiledFunctions() {
  Heap* heap = isolate_->heap();
  HandleScope scope(isolate_);
  const int compiled_funcs_count =
      EnumerateCompiledFunctions(heap, nullptr, nullptr);
  ScopedVector<Handle<SharedFunctionInfo>> sfis(compiled_funcs_count);
  ScopedVector<Handle<AbstractCode>> code_objects(compiled_funcs_count);
  EnumerateCompiledFunctions(heap, sfis.begin(), code_objects.begin());

  // During iteration, there can be heap allocation due to
  // GetScriptLineNumber call.
  for (int i = 0; i < compiled_funcs_count; ++i) {
    SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate_, sfis[i]);
    if (sfis[i]->function_data().IsInterpreterData()) {
      LogExistingFunction(
          sfis[i],
          Handle<AbstractCode>(
              AbstractCode::cast(sfis[i]->InterpreterTrampoline()), isolate_),
          CodeEventListener::INTERPRETED_FUNCTION_TAG);
    }
    if (code_objects[i].is_identical_to(BUILTIN_CODE(isolate_, CompileLazy)))
      continue;
    LogExistingFunction(sfis[i], code_objects[i]);
  }

  const int wasm_module_objects_count =
      EnumerateWasmModuleObjects(heap, nullptr);
  std::unique_ptr<Handle<WasmModuleObject>[]> module_objects(
      new Handle<WasmModuleObject>[wasm_module_objects_count]);
  EnumerateWasmModuleObjects(heap, module_objects.get());
  for (int i = 0; i < wasm_module_objects_count; ++i) {
    module_objects[i]->native_module()->LogWasmCodes(isolate_);
  }
}

void ExistingCodeLogger::LogExistingFunction(
    Handle<SharedFunctionInfo> shared, Handle<AbstractCode> code,
    CodeEventListener::LogEventsAndTags tag) {
  if (shared->script().IsScript()) {
    Handle<Script> script(Script::cast(shared->script()), isolate_);
    int line_num = Script::GetLineNumber(script, shared->StartPosition()) + 1;
    int column_num =
        Script::GetColumnNumber(script, shared->StartPosition()) + 1;
    if (script->name().IsString()) {
      Handle<String> script_name(String::cast(script->name()), isolate_);
      if (line_num > 0) {
        CALL_CODE_EVENT_HANDLER(
            CodeCreateEvent(Logger::ToNativeByScript(tag, *script), *code,
                            *shared, *script_name, line_num, column_num))
      } else {
        // Can't distinguish eval and script here, so always use Script.
        CALL_CODE_EVENT_HANDLER(CodeCreateEvent(
            Logger::ToNativeByScript(CodeEventListener::SCRIPT_TAG, *script),
            *code, *shared, *script_name))
      }
    } else {
      CALL_CODE_EVENT_HANDLER(CodeCreateEvent(
          Logger::ToNativeByScript(tag, *script), *code, *shared,
          ReadOnlyRoots(isolate_).empty_string(), line_num, column_num))
    }
  } else if (shared->IsApiFunction()) {
    // API function.
    FunctionTemplateInfo fun_data = shared->get_api_func_data();
    Object raw_call_data = fun_data.call_code();
    if (!raw_call_data.IsUndefined(isolate_)) {
      CallHandlerInfo call_data = CallHandlerInfo::cast(raw_call_data);
      Object callback_obj = call_data.callback();
      Address entry_point = v8::ToCData<Address>(callback_obj);
#if USES_FUNCTION_DESCRIPTORS
      entry_point = *FUNCTION_ENTRYPOINT_ADDRESS(entry_point);
#endif
      CALL_CODE_EVENT_HANDLER(CallbackEvent(shared->DebugName(), entry_point))
    }
  }
}

#undef CALL_CODE_EVENT_HANDLER

}  // namespace internal
}  // namespace v8
