// 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.

#ifndef RUNTIME_VM_V8_SNAPSHOT_WRITER_H_
#define RUNTIME_VM_V8_SNAPSHOT_WRITER_H_

#include <utility>

#include "platform/assert.h"
#include "vm/allocation.h"
#include "vm/hash_map.h"
#include "vm/hash_table.h"
#include "vm/json_writer.h"
#include "vm/object.h"

namespace dart {

enum class IdSpace : uint8_t {
  kInvalid = 0,   // So default-constructed ObjectIds are invalid.
  kSnapshot = 1,  // Can be VM or Isolate heap, they share ids.
  kVmText = 2,
  kIsolateText = 3,
  kVmData = 4,
  kIsolateData = 5,
  kArtificial = 6,  // Artificial objects (e.g. the global root).
  // Change ObjectId::kIdSpaceBits to use last entry if more are added.
};

class V8SnapshotProfileWriter : public ZoneAllocated {
 public:
  struct ObjectId {
    ObjectId() : ObjectId(IdSpace::kInvalid, -1) {}
    ObjectId(IdSpace space, int64_t nonce)
        : encoded_((static_cast<uint64_t>(nonce) << kIdSpaceBits) |
                   static_cast<intptr_t>(space)) {
      ASSERT(Utils::IsInt(kBitsPerInt64 - kIdSpaceBits, nonce));
    }

    inline bool operator!=(const ObjectId& other) const {
      return encoded_ != other.encoded_;
    }
    inline bool operator==(const ObjectId& other) const {
      return !(*this != other);
    }

    inline uword Hash() const { return Utils::WordHash(encoded_); }
    inline int64_t nonce() const { return encoded_ >> kIdSpaceBits; }
    inline IdSpace space() const {
      return static_cast<IdSpace>(encoded_ & kIdSpaceMask);
    }
    inline bool IsArtificial() const { return space() == IdSpace::kArtificial; }

    const char* ToCString(Zone* zone) const;
    void Write(JSONWriter* writer, const char* property = nullptr) const;
    void WriteDebug(JSONWriter* writer, const char* property = nullptr) const;

   private:
    static constexpr size_t kIdSpaceBits =
        Utils::BitLength(static_cast<int64_t>(IdSpace::kArtificial));
    static constexpr int64_t kIdSpaceMask =
        Utils::NBitMask<int64_t>(kIdSpaceBits);
    static const char* IdSpaceToCString(IdSpace space);

    int64_t encoded_;
  };

  struct Reference {
    enum class Type {
      kElement,
      kProperty,
    } type;
    intptr_t offset;   // kElement
    const char* name;  // kProperty

    static Reference Element(intptr_t offset) {
      return {Type::kElement, offset, nullptr};
    }
    static Reference Property(const char* name) {
      return {Type::kProperty, 0, name};
    }

    bool IsElement() const { return type == Type::kElement; }
  };

  static const ObjectId kArtificialRootId;

#if !defined(DART_PRECOMPILER)
  explicit V8SnapshotProfileWriter(Zone* zone) {}
  virtual ~V8SnapshotProfileWriter() {}

  void SetObjectTypeAndName(const ObjectId& object_id,
                            const char* type,
                            const char* name) {}
  void AttributeBytesTo(const ObjectId& object_id, size_t num_bytes) {}
  void AttributeReferenceTo(const ObjectId& from_object_id,
                            const Reference& reference,
                            const ObjectId& to_object_id) {}
  void AttributeWeakReferenceTo(const ObjectId& from_object_id,
                                const Reference& reference,
                                const ObjectId& to_object_id,
                                const ObjectId& replacement_object_id) {}
  void AddRoot(const ObjectId& object_id, const char* name = nullptr) {}
  bool HasId(const ObjectId& object_id) { return false; }
#else
  explicit V8SnapshotProfileWriter(Zone* zone);
  virtual ~V8SnapshotProfileWriter() {}

  // Records that the object referenced by 'object_id' has type 'type'. The
  // 'type' for all 'Instance's should be 'Instance', not the user-visible type
  // and use 'name' for the real type instead.
  void SetObjectTypeAndName(const ObjectId& object_id,
                            const char* type,
                            const char* name);

  // Charges 'num_bytes'-many bytes to 'object_id'. In a clustered snapshot,
  // objects can have their data spread across multiple sections, so this can be
  // called multiple times for the same object.
  void AttributeBytesTo(const ObjectId& object_id, size_t num_bytes);

  // Records that a reference to the object with id 'to_object_id' was written
  // in order to serialize the object with id 'from_object_id'. This does not
  // affect the number of bytes charged to 'from_object_id'.
  void AttributeReferenceTo(const ObjectId& from_object_id,
                            const Reference& reference,
                            const ObjectId& to_object_id);

  // Records that a weak serialization reference to a dropped object
  // with id 'to_object_id' was written in order to serialize the object with id
  // 'from_object_id'. 'to_object_id' must be an artificial node and
  // 'replacement_object_id' is recorded as the replacement for the
  // dropped object in the snapshot. This does not affect the number of
  // bytes charged to 'from_object_id'.
  void AttributeDroppedReferenceTo(const ObjectId& from_object_id,
                                   const Reference& reference,
                                   const ObjectId& to_object_id,
                                   const ObjectId& replacement_object_id);

  // Marks an object as being a root in the graph. Used for analysis of
  // the graph.
  void AddRoot(const ObjectId& object_id, const char* name = nullptr);

  // Write to a file in the V8 Snapshot Profile (JSON/.heapsnapshot) format.
  void Write(const char* file);

  // Whether the given object ID has been added to the profile (via AddRoot,
  // SetObjectTypeAndName, etc.).
  bool HasId(const ObjectId& object_id);

 private:
  static constexpr intptr_t kInvalidString =
      CStringIntMapKeyValueTrait::kNoValue;
  static constexpr intptr_t kNumNodeFields = 5;
  static constexpr intptr_t kNumEdgeFields = 3;

  struct Edge {
    enum class Type : intptr_t {
      kInvalid = -1,
      kContext = 0,
      kElement = 1,
      kProperty = 2,
      kInternal = 3,
      kHidden = 4,
      kShortcut = 5,
      kWeak = 6,
      kExtra = 7,
    };

    Edge() : Edge(nullptr, Type::kInvalid, -1) {}
    Edge(V8SnapshotProfileWriter* profile_writer, const Reference& reference)
        : Edge(profile_writer,
               reference.type == Reference::Type::kElement ? Type::kElement
                                                           : Type::kProperty,
               reference.type == Reference::Type::kElement
                   ? reference.offset
                   : profile_writer->strings_.Add(reference.name)) {}
    Edge(V8SnapshotProfileWriter* profile_writer,
         Type type,
         intptr_t name_or_offset)
        : type(type),
          name_or_offset(name_or_offset),
          profile_writer_(profile_writer) {}

    inline bool operator!=(const Edge& other) {
      return profile_writer_ != other.profile_writer_ || type != other.type ||
             name_or_offset != other.name_or_offset;
    }
    inline bool operator==(const Edge& other) { return !(*this != other); }

    void Write(JSONWriter* writer, const ObjectId& target_id) const;
    void WriteDebug(JSONWriter* writer, const ObjectId& target_id) const;

    Type type;
    intptr_t name_or_offset;

   private:
    V8SnapshotProfileWriter* profile_writer_;
  };

  struct EdgeToObjectIdMapTrait {
    using Key = Edge;
    using Value = ObjectId;

    struct Pair {
      Pair() : edge{}, target(kArtificialRootId) {}
      Pair(Key key, Value value) : edge(key), target(value) {}
      Edge edge;
      ObjectId target;
    };

    static Key KeyOf(Pair kv) { return kv.edge; }
    static Value ValueOf(Pair kv) { return kv.target; }
    static uword Hash(Key key) {
      return FinalizeHash(
          CombineHashes(static_cast<intptr_t>(key.type), key.name_or_offset));
    }
    static bool IsKeyEqual(Pair kv, Key key) { return kv.edge == key; }
  };

  struct EdgeMap : public ZoneDirectChainedHashMap<EdgeToObjectIdMapTrait> {
    explicit EdgeMap(Zone* zone)
        : ZoneDirectChainedHashMap<EdgeToObjectIdMapTrait>(zone) {}

    const char* ToCString(Zone* zone) const;
    void WriteDebug(JSONWriter* writer, const char* property = nullptr) const;
  };

  struct NodeInfo {
    NodeInfo() {}
    NodeInfo(V8SnapshotProfileWriter* profile_writer,
             const ObjectId& id,
             intptr_t type = kInvalidString,
             intptr_t name = kInvalidString)
        : id(id),
          type(type),
          name(name),
          edges(new (profile_writer->zone_) EdgeMap(profile_writer->zone_)),
          profile_writer_(profile_writer) {}

    inline bool operator!=(const NodeInfo& other) {
      return id != other.id || type != other.type || name != other.name ||
             self_size != other.self_size || edges != other.edges ||
             offset_ != other.offset_ ||
             profile_writer_ != other.profile_writer_;
    }
    inline bool operator==(const NodeInfo& other) { return !(*this != other); }

    void AddEdge(const Edge& edge, const ObjectId& target) {
      edges->Insert({edge, target});
    }
    bool HasEdge(const Edge& edge) { return edges->HasKey(edge); }

    const char* ToCString(Zone* zone) const;
    void Write(JSONWriter* writer) const;
    void WriteDebug(JSONWriter* writer) const;

    intptr_t offset() const { return offset_; }
    void set_offset(intptr_t offset) {
      ASSERT_EQUAL(offset_, -1);
      offset_ = offset;
    }

    ObjectId id;
    intptr_t type = kInvalidString;
    intptr_t name = kInvalidString;
    intptr_t self_size = 0;
    EdgeMap* edges = nullptr;

   private:
    // Populated during serialization.
    intptr_t offset_ = -1;
    // 'trace_node_id' isn't supported.
    // 'edge_count' is computed on-demand.

    // Used for debugging prints and creating default names if none given.
    V8SnapshotProfileWriter* profile_writer_ = nullptr;
  };

  NodeInfo* EnsureId(const ObjectId& object_id);
  void Write(JSONWriter* writer);

  // Class that encapsulates both an array of strings and a mapping from
  // strings to their index in the array.
  class StringsTable {
   public:
    explicit StringsTable(Zone* zone)
        : zone_(zone), index_map_(zone), strings_(zone, 2) {}

    intptr_t Add(const char* str);
    intptr_t AddFormatted(const char* fmt, ...) PRINTF_ATTRIBUTE(2, 3);
    const char* At(intptr_t index) const;
    void Write(JSONWriter* writer, const char* property = nullptr) const;

   private:
    Zone* zone_;
    CStringIntMap index_map_;
    GrowableArray<const char*> strings_;
  };

  struct ObjectIdToNodeInfoTraits {
    typedef NodeInfo Pair;
    typedef ObjectId Key;
    typedef Pair Value;

    static Key KeyOf(const Pair& pair) { return pair.id; }

    static Value ValueOf(const Pair& pair) { return pair; }

    static uword Hash(const Key& key) { return key.Hash(); }

    static bool IsKeyEqual(const Pair& x, const Key& y) { return x.id == y; }
  };

  struct ObjectIdSetKeyValueTrait {
    using Pair = ObjectId;
    using Key = Pair;
    using Value = Pair;

    static Key KeyOf(const Pair& pair) { return pair; }
    static Value ValueOf(const Pair& pair) { return pair; }
    static uword Hash(const Key& key) { return key.Hash(); }
    static bool IsKeyEqual(const Pair& pair, const Key& key) {
      return pair == key;
    }
  };

  Zone* const zone_;
  DirectChainedHashMap<ObjectIdToNodeInfoTraits> nodes_;
  StringsTable node_types_;
  StringsTable edge_types_;
  StringsTable strings_;
  DirectChainedHashMap<ObjectIdSetKeyValueTrait> roots_;
#endif
};

}  // namespace dart

#endif  //  RUNTIME_VM_V8_SNAPSHOT_WRITER_H_
