// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/v8_snapshot_writer.h"

#include "vm/dart.h"
#include "vm/os.h"

namespace dart {

const V8SnapshotProfileWriter::ObjectId
    V8SnapshotProfileWriter::kArtificialRootId{IdSpace::kArtificial, 0};

#if defined(DART_PRECOMPILER)

V8SnapshotProfileWriter::V8SnapshotProfileWriter(Zone* zone)
    : zone_(zone),
      node_types_(zone_),
      edge_types_(zone_),
      strings_(zone_),
      roots_(zone_) {
  intptr_t idx = edge_types_.Add("context");
  ASSERT_EQUAL(idx, static_cast<intptr_t>(Edge::Type::kContext));
  idx = edge_types_.Add("element");
  ASSERT_EQUAL(idx, static_cast<intptr_t>(Edge::Type::kElement));
  idx = edge_types_.Add("property");
  ASSERT_EQUAL(idx, static_cast<intptr_t>(Edge::Type::kProperty));
  idx = edge_types_.Add("internal");
  ASSERT_EQUAL(idx, static_cast<intptr_t>(Edge::Type::kInternal));

  SetObjectTypeAndName(kArtificialRootId, "ArtificialRoot",
                       "<artificial root>");
}

void V8SnapshotProfileWriter::SetObjectTypeAndName(const ObjectId& object_id,
                                                   const char* type,
                                                   const char* name) {
  ASSERT(type != nullptr);
  NodeInfo* info = EnsureId(object_id);
  const intptr_t type_index = node_types_.Add(type);
  if (info->type != kInvalidString && info->type != type_index) {
    FATAL("Attempting to assign mismatching type %s to node %s", type,
          info->ToCString(zone_));
  }
  info->type = type_index;
  // Don't overwrite any existing name.
  if (info->name == kInvalidString) {
    info->name = strings_.Add(name);
  }
}

void V8SnapshotProfileWriter::AttributeBytesTo(const ObjectId& object_id,
                                               size_t num_bytes) {
  EnsureId(object_id)->self_size += num_bytes;
}

void V8SnapshotProfileWriter::AttributeReferenceTo(
    const ObjectId& from_object_id,
    const Reference& reference,
    const ObjectId& to_object_id) {
  ASSERT(reference.IsElement() ? reference.offset >= 0
                               : reference.name != nullptr);
  EnsureId(to_object_id);
  const Edge edge(this, reference);
  EnsureId(from_object_id)->AddEdge(edge, to_object_id);
}

void V8SnapshotProfileWriter::AttributeDroppedReferenceTo(
    const ObjectId& from_object_id,
    const Reference& reference,
    const ObjectId& to_object_id,
    const ObjectId& replacement_object_id) {
  ASSERT(to_object_id.IsArtificial());
  ASSERT(!replacement_object_id.IsArtificial());
  ASSERT(reference.IsElement() ? reference.offset >= 0
                               : reference.name != nullptr);

  // The target node is added normally.
  AttributeReferenceTo(from_object_id, reference, to_object_id);

  EnsureId(replacement_object_id);
  // Put the replacement node at an invalid offset or name that can still be
  // associated with the real one. For offsets, this is the negative offset.
  // For names, it's the name prefixed with ":replacement_".
  Reference replacement_reference =
      reference.IsElement() ? Reference::Element(-reference.offset)
                            : Reference::Property(OS::SCreate(
                                  zone_, ":replacement_%s", reference.name));
  const Edge replacement_edge(this, replacement_reference);
  EnsureId(from_object_id)->AddEdge(replacement_edge, replacement_object_id);
}

bool V8SnapshotProfileWriter::HasId(const ObjectId& object_id) {
  return nodes_.HasKey(object_id);
}

V8SnapshotProfileWriter::NodeInfo* V8SnapshotProfileWriter::EnsureId(
    const ObjectId& object_id) {
  if (!HasId(object_id)) {
    nodes_.Insert(NodeInfo(this, object_id));
  }
  return nodes_.Lookup(object_id);
}

const char* V8SnapshotProfileWriter::NodeInfo::ToCString(Zone* zone) const {
  JSONWriter writer;
  WriteDebug(&writer);
  return OS::SCreate(zone, "%s", writer.buffer()->buffer());
}

void V8SnapshotProfileWriter::NodeInfo::Write(JSONWriter* writer) const {
  ASSERT(id.space() != IdSpace::kInvalid);
  if (type == kInvalidString) {
    FATAL("No type given for node %s", id.ToCString(profile_writer_->zone_));
  }
  writer->PrintValue(type);
  if (name != kInvalidString) {
    writer->PrintValue(name);
  } else {
    ASSERT(profile_writer_ != nullptr);
    // If we don't already have a name for the node, we lazily create a default
    // one. This is safe since the strings table is written out after the nodes.
    const intptr_t name = profile_writer_->strings_.AddFormatted(
        "Unnamed [%s] (nil)", profile_writer_->node_types_.At(type));
    writer->PrintValue(name);
  }
  id.Write(writer);
  writer->PrintValue(self_size);
  writer->PrintValue64(edges->Length());
}

void V8SnapshotProfileWriter::NodeInfo::WriteDebug(JSONWriter* writer) const {
  writer->OpenObject();
  if (type != kInvalidString) {
    writer->PrintProperty("type", profile_writer_->node_types_.At(type));
  }
  if (name != kInvalidString) {
    writer->PrintProperty("name", profile_writer_->strings_.At(name));
  }
  id.WriteDebug(writer, "id");
  writer->PrintProperty("self_size", self_size);
  edges->WriteDebug(writer, "edges");
  writer->CloseObject();
}

const char* V8SnapshotProfileWriter::ObjectId::ToCString(Zone* zone) const {
  JSONWriter writer;
  WriteDebug(&writer);
  return OS::SCreate(zone, "%s", writer.buffer()->buffer());
}

void V8SnapshotProfileWriter::ObjectId::Write(JSONWriter* writer,
                                              const char* property) const {
  if (property != nullptr) {
    writer->PrintProperty64(property, encoded_);
  } else {
    writer->PrintValue64(encoded_);
  }
}

void V8SnapshotProfileWriter::ObjectId::WriteDebug(JSONWriter* writer,
                                                   const char* property) const {
  writer->OpenObject(property);
  writer->PrintProperty("space", IdSpaceToCString(space()));
  writer->PrintProperty64("nonce", nonce());
  writer->CloseObject();
}

const char* V8SnapshotProfileWriter::ObjectId::IdSpaceToCString(IdSpace space) {
  switch (space) {
    case IdSpace::kInvalid:
      return "Invalid";
    case IdSpace::kSnapshot:
      return "Snapshot";
    case IdSpace::kVmText:
      return "VmText";
    case IdSpace::kIsolateText:
      return "IsolateText";
    case IdSpace::kVmData:
      return "VmData";
    case IdSpace::kIsolateData:
      return "IsolateData";
    case IdSpace::kArtificial:
      return "Artificial";
    default:
      UNREACHABLE();
  }
}

const char* V8SnapshotProfileWriter::EdgeMap::ToCString(Zone* zone) const {
  JSONWriter writer;
  WriteDebug(&writer);
  return OS::SCreate(zone, "%s", writer.buffer()->buffer());
}

void V8SnapshotProfileWriter::EdgeMap::WriteDebug(JSONWriter* writer,
                                                  const char* property) const {
  writer->OpenArray(property);
  auto edge_it = GetIterator();
  while (auto const pair = edge_it.Next()) {
    pair->edge.WriteDebug(writer, pair->target);
  }
  writer->CloseArray();
}

void V8SnapshotProfileWriter::Edge::Write(JSONWriter* writer,
                                          const ObjectId& target_id) const {
  ASSERT(type != Type::kInvalid);
  writer->PrintValue64(static_cast<intptr_t>(type));
  writer->PrintValue64(name_or_offset);
  auto const target = profile_writer_->nodes_.LookupValue(target_id);
  writer->PrintValue64(target.offset());
}

void V8SnapshotProfileWriter::Edge::WriteDebug(
    JSONWriter* writer,
    const ObjectId& target_id) const {
  writer->OpenObject();
  if (type != Type::kInvalid) {
    writer->PrintProperty(
        "type", profile_writer_->edge_types_.At(static_cast<intptr_t>(type)));
  }
  if (type == Type::kProperty) {
    writer->PrintProperty("name", profile_writer_->strings_.At(name_or_offset));
  } else {
    writer->PrintProperty64("offset", name_or_offset);
  }
  auto const target = profile_writer_->nodes_.LookupValue(target_id);
  target.id.WriteDebug(writer, "target");
  writer->CloseObject();
}

void V8SnapshotProfileWriter::AddRoot(const ObjectId& object_id,
                                      const char* name) {
  // HeapSnapshotWorker.HeapSnapshot.calculateDistances (from HeapSnapshot.js)
  // assumes that the root does not have more than one edge to any other node
  // (most likely an oversight).
  if (roots_.HasKey(object_id)) return;
  roots_.Insert(object_id);

  auto const str_index = strings_.Add(name);
  auto const root = nodes_.Lookup(kArtificialRootId);
  ASSERT(root != nullptr);
  root->AddEdge(str_index != kInvalidString
                    ? Edge(this, Edge::Type::kProperty, str_index)
                    : Edge(this, Edge::Type::kInternal, root->edges->Length()),
                object_id);
}

intptr_t V8SnapshotProfileWriter::StringsTable::Add(const char* str) {
  if (str == nullptr) return kInvalidString;
  if (auto const kv = index_map_.Lookup(str)) {
    return kv->value;
  }
  const char* new_str = OS::SCreate(zone_, "%s", str);
  const intptr_t index = strings_.length();
  strings_.Add(new_str);
  index_map_.Insert({new_str, index});
  return index;
}

intptr_t V8SnapshotProfileWriter::StringsTable::AddFormatted(const char* fmt,
                                                             ...) {
  va_list args;
  va_start(args, fmt);
  const char* str = OS::VSCreate(zone_, fmt, args);
  if (auto const kv = index_map_.Lookup(str)) {
    return kv->value;
  }
  const intptr_t index = strings_.length();
  strings_.Add(str);
  index_map_.Insert({str, index});
  return index;
}

const char* V8SnapshotProfileWriter::StringsTable::At(intptr_t index) const {
  if (index > strings_.length()) return nullptr;
  return strings_[index];
}

void V8SnapshotProfileWriter::StringsTable::Write(JSONWriter* writer,
                                                  const char* property) const {
  writer->OpenArray(property);
  for (auto const str : strings_) {
    writer->PrintValue(str);
    writer->PrintNewline();
  }
  writer->CloseArray();
}

void V8SnapshotProfileWriter::Write(JSONWriter* writer) {
  writer->OpenObject();

  writer->OpenObject("snapshot");
  {
    writer->OpenObject("meta");

    {
      writer->OpenArray("node_fields");
      writer->PrintValue("type");
      writer->PrintValue("name");
      writer->PrintValue("id");
      writer->PrintValue("self_size");
      writer->PrintValue("edge_count");
      writer->CloseArray();
    }

    {
      writer->OpenArray("node_types");
      node_types_.Write(writer);
      writer->CloseArray();
    }

    {
      writer->OpenArray("edge_fields");
      writer->PrintValue("type");
      writer->PrintValue("name_or_index");
      writer->PrintValue("to_node");
      writer->CloseArray();
    }

    {
      writer->OpenArray("edge_types");
      edge_types_.Write(writer);
      writer->CloseArray();
    }

    writer->CloseObject();

    writer->PrintProperty64("node_count", nodes_.Size());
    {
      intptr_t edge_count = 0;
      auto nodes_it = nodes_.GetIterator();
      while (auto const info = nodes_it.Next()) {
        // All nodes should have an edge map, though it may be empty.
        ASSERT(info->edges != nullptr);
        edge_count += info->edges->Length();
      }
      writer->PrintProperty64("edge_count", edge_count);
    }
  }
  writer->CloseObject();

  {
    writer->OpenArray("nodes");
    //  Always write the information for the artificial root first.
    auto const root = nodes_.Lookup(kArtificialRootId);
    ASSERT(root != nullptr);
    intptr_t offset = 0;
    root->set_offset(offset);
    root->Write(writer);
    offset += kNumNodeFields;
    auto nodes_it = nodes_.GetIterator();
    for (auto entry = nodes_it.Next(); entry != nullptr;
         entry = nodes_it.Next()) {
      if (entry->id == kArtificialRootId) continue;
      entry->set_offset(offset);
      entry->Write(writer);
      offset += kNumNodeFields;
    }
    writer->CloseArray();
  }

  {
    auto write_edges = [&](const NodeInfo& info) {
      auto edges_it = info.edges->GetIterator();
      while (auto const pair = edges_it.Next()) {
        pair->edge.Write(writer, pair->target);
      }
    };
    writer->OpenArray("edges");
    //  Always write the information for the artificial root first.
    auto const root = nodes_.Lookup(kArtificialRootId);
    ASSERT(root != nullptr);
    write_edges(*root);
    auto nodes_it = nodes_.GetIterator();
    while (auto const entry = nodes_it.Next()) {
      if (entry->id == kArtificialRootId) continue;
      write_edges(*entry);
    }
    writer->CloseArray();
  }

  // Must happen after any calls to WriteNodeInfo, as those calls may add more
  // strings.
  strings_.Write(writer, "strings");

  writer->CloseObject();
}

void V8SnapshotProfileWriter::Write(const char* filename) {
  JSONWriter json;
  Write(&json);

  auto file_open = Dart::file_open_callback();
  auto file_write = Dart::file_write_callback();
  auto file_close = Dart::file_close_callback();
  if ((file_open == nullptr) || (file_write == nullptr) ||
      (file_close == nullptr)) {
    OS::PrintErr("Could not access file callbacks to write snapshot profile.");
    return;
  }

  auto file = file_open(filename, /*write=*/true);
  if (file == nullptr) {
    OS::PrintErr("Failed to open file %s\n", filename);
  } else {
    char* output = nullptr;
    intptr_t output_length = 0;
    json.Steal(&output, &output_length);
    file_write(output, output_length, file);
    free(output);
    file_close(file);
  }
}

#endif

}  // namespace dart
