// 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::NBitMaskUnsafe(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_
