// Copyright 2013 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_CRANKSHAFT_UNIQUE_H_
#define V8_CRANKSHAFT_UNIQUE_H_

#include <ostream>  // NOLINT(readability/streams)

#include "src/assert-scope.h"
#include "src/base/functional.h"
#include "src/handles.h"
#include "src/utils.h"
#include "src/zone.h"

namespace v8 {
namespace internal {


template <typename T>
class UniqueSet;


// Represents a handle to an object on the heap, but with the additional
// ability of checking for equality and hashing without accessing the heap.
//
// Creating a Unique<T> requires first dereferencing the handle to obtain
// the address of the object, which is used as the hashcode and the basis for
// comparison. The object can be moved later by the GC, but comparison
// and hashing use the old address of the object, without dereferencing it.
//
// Careful! Comparison of two Uniques is only correct if both were created
// in the same "era" of GC or if at least one is a non-movable object.
template <typename T>
class Unique final {
 public:
  Unique<T>() : raw_address_(NULL) {}

  // TODO(titzer): make private and introduce a uniqueness scope.
  explicit Unique(Handle<T> handle) {
    if (handle.is_null()) {
      raw_address_ = NULL;
    } else {
      // This is a best-effort check to prevent comparing Unique<T>'s created
      // in different GC eras; we require heap allocation to be disallowed at
      // creation time.
      // NOTE: we currently consider maps to be non-movable, so no special
      // assurance is required for creating a Unique<Map>.
      // TODO(titzer): other immortable immovable objects are also fine.
      DCHECK(!AllowHeapAllocation::IsAllowed() || handle->IsMap());
      raw_address_ = reinterpret_cast<Address>(*handle);
      DCHECK_NOT_NULL(raw_address_);  // Non-null should imply non-zero address.
    }
    handle_ = handle;
  }

  // Constructor for handling automatic up casting.
  // Eg. Unique<JSFunction> can be passed when Unique<Object> is expected.
  template <class S> Unique(Unique<S> uniq) {
#ifdef DEBUG
    T* a = NULL;
    S* b = NULL;
    a = b;  // Fake assignment to enforce type checks.
    USE(a);
#endif
    raw_address_ = uniq.raw_address_;
    handle_ = uniq.handle_;
  }

  template <typename U>
  inline bool operator==(const Unique<U>& other) const {
    DCHECK(IsInitialized() && other.IsInitialized());
    return raw_address_ == other.raw_address_;
  }

  template <typename U>
  inline bool operator!=(const Unique<U>& other) const {
    DCHECK(IsInitialized() && other.IsInitialized());
    return raw_address_ != other.raw_address_;
  }

  friend inline size_t hash_value(Unique<T> const& unique) {
    DCHECK(unique.IsInitialized());
    return base::hash<void*>()(unique.raw_address_);
  }

  inline intptr_t Hashcode() const {
    DCHECK(IsInitialized());
    return reinterpret_cast<intptr_t>(raw_address_);
  }

  inline bool IsNull() const {
    DCHECK(IsInitialized());
    return raw_address_ == NULL;
  }

  inline bool IsKnownGlobal(void* global) const {
    DCHECK(IsInitialized());
    return raw_address_ == reinterpret_cast<Address>(global);
  }

  inline Handle<T> handle() const {
    return handle_;
  }

  template <class S> static Unique<T> cast(Unique<S> that) {
    // Allow fetching location() to unsafe-cast the handle. This is necessary
    // since we can't concurrently safe-cast. Safe-casting requires looking at
    // the heap which may be moving concurrently to the compiler thread.
    AllowHandleDereference allow_deref;
    return Unique<T>(that.raw_address_,
                     Handle<T>(reinterpret_cast<T**>(that.handle_.location())));
  }

  inline bool IsInitialized() const {
    return raw_address_ != NULL || handle_.is_null();
  }

  // TODO(titzer): this is a hack to migrate to Unique<T> incrementally.
  static Unique<T> CreateUninitialized(Handle<T> handle) {
    return Unique<T>(NULL, handle);
  }

  static Unique<T> CreateImmovable(Handle<T> handle) {
    return Unique<T>(reinterpret_cast<Address>(*handle), handle);
  }

 private:
  Unique(Address raw_address, Handle<T> handle)
      : raw_address_(raw_address), handle_(handle) {}

  Address raw_address_;
  Handle<T> handle_;

  friend class UniqueSet<T>;  // Uses internal details for speed.
  template <class U>
  friend class Unique;  // For comparing raw_address values.
};

template <typename T>
inline std::ostream& operator<<(std::ostream& os, Unique<T> uniq) {
  return os << Brief(*uniq.handle());
}


template <typename T>
class UniqueSet final : public ZoneObject {
 public:
  // Constructor. A new set will be empty.
  UniqueSet() : size_(0), capacity_(0), array_(NULL) { }

  // Capacity constructor. A new set will be empty.
  UniqueSet(int capacity, Zone* zone)
      : size_(0), capacity_(capacity),
        array_(zone->NewArray<Unique<T> >(capacity)) {
    DCHECK(capacity <= kMaxCapacity);
  }

  // Singleton constructor.
  UniqueSet(Unique<T> uniq, Zone* zone)
      : size_(1), capacity_(1), array_(zone->NewArray<Unique<T> >(1)) {
    array_[0] = uniq;
  }

  // Add a new element to this unique set. Mutates this set. O(|this|).
  void Add(Unique<T> uniq, Zone* zone) {
    DCHECK(uniq.IsInitialized());
    // Keep the set sorted by the {raw_address} of the unique elements.
    for (int i = 0; i < size_; i++) {
      if (array_[i] == uniq) return;
      if (array_[i].raw_address_ > uniq.raw_address_) {
        // Insert in the middle.
        Grow(size_ + 1, zone);
        for (int j = size_ - 1; j >= i; j--) array_[j + 1] = array_[j];
        array_[i] = uniq;
        size_++;
        return;
      }
    }
    // Append the element to the the end.
    Grow(size_ + 1, zone);
    array_[size_++] = uniq;
  }

  // Remove an element from this set. Mutates this set. O(|this|)
  void Remove(Unique<T> uniq) {
    for (int i = 0; i < size_; i++) {
      if (array_[i] == uniq) {
        while (++i < size_) array_[i - 1] = array_[i];
        size_--;
        return;
      }
    }
  }

  // Compare this set against another set. O(|this|).
  bool Equals(const UniqueSet<T>* that) const {
    if (that->size_ != this->size_) return false;
    for (int i = 0; i < this->size_; i++) {
      if (this->array_[i] != that->array_[i]) return false;
    }
    return true;
  }

  // Check whether this set contains the given element. O(|this|)
  // TODO(titzer): use binary search for large sets to make this O(log|this|)
  template <typename U>
  bool Contains(const Unique<U> elem) const {
    for (int i = 0; i < this->size_; ++i) {
      Unique<T> cand = this->array_[i];
      if (cand.raw_address_ >= elem.raw_address_) {
        return cand.raw_address_ == elem.raw_address_;
      }
    }
    return false;
  }

  // Check if this set is a subset of the given set. O(|this| + |that|).
  bool IsSubset(const UniqueSet<T>* that) const {
    if (that->size_ < this->size_) return false;
    int j = 0;
    for (int i = 0; i < this->size_; i++) {
      Unique<T> sought = this->array_[i];
      while (true) {
        if (sought == that->array_[j++]) break;
        // Fail whenever there are more elements in {this} than {that}.
        if ((this->size_ - i) > (that->size_ - j)) return false;
      }
    }
    return true;
  }

  // Returns a new set representing the intersection of this set and the other.
  // O(|this| + |that|).
  UniqueSet<T>* Intersect(const UniqueSet<T>* that, Zone* zone) const {
    if (that->size_ == 0 || this->size_ == 0) return new(zone) UniqueSet<T>();

    UniqueSet<T>* out = new(zone) UniqueSet<T>(
        Min(this->size_, that->size_), zone);

    int i = 0, j = 0, k = 0;
    while (i < this->size_ && j < that->size_) {
      Unique<T> a = this->array_[i];
      Unique<T> b = that->array_[j];
      if (a == b) {
        out->array_[k++] = a;
        i++;
        j++;
      } else if (a.raw_address_ < b.raw_address_) {
        i++;
      } else {
        j++;
      }
    }

    out->size_ = k;
    return out;
  }

  // Returns a new set representing the union of this set and the other.
  // O(|this| + |that|).
  UniqueSet<T>* Union(const UniqueSet<T>* that, Zone* zone) const {
    if (that->size_ == 0) return this->Copy(zone);
    if (this->size_ == 0) return that->Copy(zone);

    UniqueSet<T>* out = new(zone) UniqueSet<T>(
        this->size_ + that->size_, zone);

    int i = 0, j = 0, k = 0;
    while (i < this->size_ && j < that->size_) {
      Unique<T> a = this->array_[i];
      Unique<T> b = that->array_[j];
      if (a == b) {
        out->array_[k++] = a;
        i++;
        j++;
      } else if (a.raw_address_ < b.raw_address_) {
        out->array_[k++] = a;
        i++;
      } else {
        out->array_[k++] = b;
        j++;
      }
    }

    while (i < this->size_) out->array_[k++] = this->array_[i++];
    while (j < that->size_) out->array_[k++] = that->array_[j++];

    out->size_ = k;
    return out;
  }

  // Returns a new set representing all elements from this set which are not in
  // that set. O(|this| * |that|).
  UniqueSet<T>* Subtract(const UniqueSet<T>* that, Zone* zone) const {
    if (that->size_ == 0) return this->Copy(zone);

    UniqueSet<T>* out = new(zone) UniqueSet<T>(this->size_, zone);

    int i = 0, j = 0;
    while (i < this->size_) {
      Unique<T> cand = this->array_[i];
      if (!that->Contains(cand)) {
        out->array_[j++] = cand;
      }
      i++;
    }

    out->size_ = j;
    return out;
  }

  // Makes an exact copy of this set. O(|this|).
  UniqueSet<T>* Copy(Zone* zone) const {
    UniqueSet<T>* copy = new(zone) UniqueSet<T>(this->size_, zone);
    copy->size_ = this->size_;
    memcpy(copy->array_, this->array_, this->size_ * sizeof(Unique<T>));
    return copy;
  }

  void Clear() {
    size_ = 0;
  }

  inline int size() const {
    return size_;
  }

  inline Unique<T> at(int index) const {
    DCHECK(index >= 0 && index < size_);
    return array_[index];
  }

 private:
  // These sets should be small, since operations are implemented with simple
  // linear algorithms. Enforce a maximum size.
  static const int kMaxCapacity = 65535;

  uint16_t size_;
  uint16_t capacity_;
  Unique<T>* array_;

  // Grow the size of internal storage to be at least {size} elements.
  void Grow(int size, Zone* zone) {
    CHECK(size < kMaxCapacity);  // Enforce maximum size.
    if (capacity_ < size) {
      int new_capacity = 2 * capacity_ + size;
      if (new_capacity > kMaxCapacity) new_capacity = kMaxCapacity;
      Unique<T>* new_array = zone->NewArray<Unique<T> >(new_capacity);
      if (size_ > 0) {
        memcpy(new_array, array_, size_ * sizeof(Unique<T>));
      }
      capacity_ = new_capacity;
      array_ = new_array;
    }
  }
};

}  // namespace internal
}  // namespace v8

#endif  // V8_CRANKSHAFT_UNIQUE_H_
