// Copyright 2012 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_DATAFLOW_H_
#define V8_DATAFLOW_H_

#include "src/allocation.h"
#include "src/zone.h"

namespace v8 {
namespace internal {

class BitVector : public ZoneObject {
 public:
  // Iterator for the elements of this BitVector.
  class Iterator BASE_EMBEDDED {
   public:
    explicit Iterator(BitVector* target)
        : target_(target),
          current_index_(0),
          current_value_(target->data_[0]),
          current_(-1) {
      DCHECK(target->data_length_ > 0);
      Advance();
    }
    ~Iterator() {}

    bool Done() const { return current_index_ >= target_->data_length_; }
    void Advance();

    int Current() const {
      DCHECK(!Done());
      return current_;
    }

   private:
    uintptr_t SkipZeroBytes(uintptr_t val) {
      while ((val & 0xFF) == 0) {
        val >>= 8;
        current_ += 8;
      }
      return val;
    }
    uintptr_t SkipZeroBits(uintptr_t val) {
      while ((val & 0x1) == 0) {
        val >>= 1;
        current_++;
      }
      return val;
    }

    BitVector* target_;
    int current_index_;
    uintptr_t current_value_;
    int current_;

    friend class BitVector;
  };

  static const int kDataBits = kPointerSize * 8;
  static const int kDataBitShift = kPointerSize == 8 ? 6 : 5;
  static const uintptr_t kOne = 1;  // This saves some static_casts.

  BitVector(int length, Zone* zone)
      : length_(length),
        data_length_(SizeFor(length)),
        data_(zone->NewArray<uintptr_t>(data_length_)) {
    DCHECK_LE(0, length);
    Clear();
  }

  BitVector(const BitVector& other, Zone* zone)
      : length_(other.length()),
        data_length_(SizeFor(length_)),
        data_(zone->NewArray<uintptr_t>(data_length_)) {
    CopyFrom(other);
  }

  static int SizeFor(int length) {
    if (length == 0) return 1;
    return 1 + ((length - 1) / kDataBits);
  }

  void CopyFrom(const BitVector& other) {
    DCHECK(other.length() <= length());
    for (int i = 0; i < other.data_length_; i++) {
      data_[i] = other.data_[i];
    }
    for (int i = other.data_length_; i < data_length_; i++) {
      data_[i] = 0;
    }
  }

  bool Contains(int i) const {
    DCHECK(i >= 0 && i < length());
    uintptr_t block = data_[i / kDataBits];
    return (block & (kOne << (i % kDataBits))) != 0;
  }

  void Add(int i) {
    DCHECK(i >= 0 && i < length());
    data_[i / kDataBits] |= (kOne << (i % kDataBits));
  }

  void AddAll() { memset(data_, -1, sizeof(uintptr_t) * data_length_); }

  void Remove(int i) {
    DCHECK(i >= 0 && i < length());
    data_[i / kDataBits] &= ~(kOne << (i % kDataBits));
  }

  void Union(const BitVector& other) {
    DCHECK(other.length() == length());
    for (int i = 0; i < data_length_; i++) {
      data_[i] |= other.data_[i];
    }
  }

  bool UnionIsChanged(const BitVector& other) {
    DCHECK(other.length() == length());
    bool changed = false;
    for (int i = 0; i < data_length_; i++) {
      uintptr_t old_data = data_[i];
      data_[i] |= other.data_[i];
      if (data_[i] != old_data) changed = true;
    }
    return changed;
  }

  void Intersect(const BitVector& other) {
    DCHECK(other.length() == length());
    for (int i = 0; i < data_length_; i++) {
      data_[i] &= other.data_[i];
    }
  }

  bool IntersectIsChanged(const BitVector& other) {
    DCHECK(other.length() == length());
    bool changed = false;
    for (int i = 0; i < data_length_; i++) {
      uintptr_t old_data = data_[i];
      data_[i] &= other.data_[i];
      if (data_[i] != old_data) changed = true;
    }
    return changed;
  }

  void Subtract(const BitVector& other) {
    DCHECK(other.length() == length());
    for (int i = 0; i < data_length_; i++) {
      data_[i] &= ~other.data_[i];
    }
  }

  void Clear() {
    for (int i = 0; i < data_length_; i++) {
      data_[i] = 0;
    }
  }

  bool IsEmpty() const {
    for (int i = 0; i < data_length_; i++) {
      if (data_[i] != 0) return false;
    }
    return true;
  }

  bool Equals(const BitVector& other) {
    for (int i = 0; i < data_length_; i++) {
      if (data_[i] != other.data_[i]) return false;
    }
    return true;
  }

  int Count() const;

  int length() const { return length_; }

#ifdef DEBUG
  void Print();
#endif

 private:
  const int length_;
  const int data_length_;
  uintptr_t* const data_;

  DISALLOW_COPY_AND_ASSIGN(BitVector);
};


class GrowableBitVector BASE_EMBEDDED {
 public:
  class Iterator BASE_EMBEDDED {
   public:
    Iterator(const GrowableBitVector* target, Zone* zone)
        : it_(target->bits_ == NULL ? new (zone) BitVector(1, zone)
                                    : target->bits_) {}
    bool Done() const { return it_.Done(); }
    void Advance() { it_.Advance(); }
    int Current() const { return it_.Current(); }

   private:
    BitVector::Iterator it_;
  };

  GrowableBitVector() : bits_(NULL) {}
  GrowableBitVector(int length, Zone* zone)
      : bits_(new (zone) BitVector(length, zone)) {}

  bool Contains(int value) const {
    if (!InBitsRange(value)) return false;
    return bits_->Contains(value);
  }

  void Add(int value, Zone* zone) {
    EnsureCapacity(value, zone);
    bits_->Add(value);
  }

  void Union(const GrowableBitVector& other, Zone* zone) {
    for (Iterator it(&other, zone); !it.Done(); it.Advance()) {
      Add(it.Current(), zone);
    }
  }

  void Clear() {
    if (bits_ != NULL) bits_->Clear();
  }

 private:
  static const int kInitialLength = 1024;

  bool InBitsRange(int value) const {
    return bits_ != NULL && bits_->length() > value;
  }

  void EnsureCapacity(int value, Zone* zone) {
    if (InBitsRange(value)) return;
    int new_length = bits_ == NULL ? kInitialLength : bits_->length();
    while (new_length <= value) new_length *= 2;
    BitVector* new_bits = new (zone) BitVector(new_length, zone);
    if (bits_ != NULL) new_bits->CopyFrom(*bits_);
    bits_ = new_bits;
  }

  BitVector* bits_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_DATAFLOW_H_
