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

#ifndef V8_SNAPSHOT_REFERENCES_H_
#define V8_SNAPSHOT_REFERENCES_H_

#include "src/base/bit-field.h"
#include "src/base/hashmap.h"
#include "src/common/assert-scope.h"
#include "src/execution/isolate.h"
#include "src/utils/identity-map.h"

namespace v8 {
namespace internal {

enum class SnapshotSpace : byte {
  kReadOnlyHeap,
  kOld,
  kCode,
  kMap,
};
static constexpr int kNumberOfSnapshotSpaces =
    static_cast<int>(SnapshotSpace::kMap) + 1;

class SerializerReference {
 private:
  enum SpecialValueType {
    kBackReference,
    kAttachedReference,
    kOffHeapBackingStore,
    kBuiltinReference,
  };

  SerializerReference(SpecialValueType type, uint32_t value)
      : bit_field_(TypeBits::encode(type) | ValueBits::encode(value)) {}

 public:
  static SerializerReference BackReference(uint32_t index) {
    return SerializerReference(kBackReference, index);
  }

  static SerializerReference OffHeapBackingStoreReference(uint32_t index) {
    return SerializerReference(kOffHeapBackingStore, index);
  }

  static SerializerReference AttachedReference(uint32_t index) {
    return SerializerReference(kAttachedReference, index);
  }

  static SerializerReference BuiltinReference(uint32_t index) {
    return SerializerReference(kBuiltinReference, index);
  }

  bool is_back_reference() const {
    return TypeBits::decode(bit_field_) == kBackReference;
  }

  uint32_t back_ref_index() const {
    DCHECK(is_back_reference());
    return ValueBits::decode(bit_field_);
  }

  bool is_off_heap_backing_store_reference() const {
    return TypeBits::decode(bit_field_) == kOffHeapBackingStore;
  }

  uint32_t off_heap_backing_store_index() const {
    DCHECK(is_off_heap_backing_store_reference());
    return ValueBits::decode(bit_field_);
  }

  bool is_attached_reference() const {
    return TypeBits::decode(bit_field_) == kAttachedReference;
  }

  uint32_t attached_reference_index() const {
    DCHECK(is_attached_reference());
    return ValueBits::decode(bit_field_);
  }

  bool is_builtin_reference() const {
    return TypeBits::decode(bit_field_) == kBuiltinReference;
  }

  uint32_t builtin_index() const {
    DCHECK(is_builtin_reference());
    return ValueBits::decode(bit_field_);
  }

 private:
  using TypeBits = base::BitField<SpecialValueType, 0, 2>;
  using ValueBits = TypeBits::Next<uint32_t, 32 - TypeBits::kSize>;

  uint32_t bit_field_;

  friend class SerializerReferenceMap;
};

// SerializerReference has to fit in an IdentityMap value field.
STATIC_ASSERT(sizeof(SerializerReference) <= sizeof(void*));

class SerializerReferenceMap {
 public:
  explicit SerializerReferenceMap(Isolate* isolate)
      : map_(isolate->heap()), attached_reference_index_(0) {}

  const SerializerReference* LookupReference(HeapObject object) const {
    return map_.Find(object);
  }

  const SerializerReference* LookupReference(Handle<HeapObject> object) const {
    return map_.Find(object);
  }

  const SerializerReference* LookupBackingStore(void* backing_store) const {
    auto it = backing_store_map_.find(backing_store);
    if (it == backing_store_map_.end()) return nullptr;
    return &it->second;
  }

  void Add(HeapObject object, SerializerReference reference) {
    DCHECK_NULL(LookupReference(object));
    map_.Insert(object, reference);
  }

  void AddBackingStore(void* backing_store, SerializerReference reference) {
    DCHECK(backing_store_map_.find(backing_store) == backing_store_map_.end());
    backing_store_map_.emplace(backing_store, reference);
  }

  SerializerReference AddAttachedReference(HeapObject object) {
    SerializerReference reference =
        SerializerReference::AttachedReference(attached_reference_index_++);
    map_.Insert(object, reference);
    return reference;
  }

 private:
  IdentityMap<SerializerReference, base::DefaultAllocationPolicy> map_;
  std::unordered_map<void*, SerializerReference> backing_store_map_;
  int attached_reference_index_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SNAPSHOT_REFERENCES_H_
