// Copyright (c) 2012, 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.

import '../universe/side_effects.dart' show SideEffects;
import 'nodes.dart';

class ValueSet {
  int size = 0;
  List<HInstruction> table;
  ValueSetNode collisions;
  ValueSet() : table = List<HInstruction>.filled(8, null);

  bool get isEmpty => size == 0;
  int get length => size;

  void add(HInstruction instruction) {
    assert(lookup(instruction) == null);
    int hashCode = instruction.gvnHashCode();
    int capacity = table.length;
    // Resize when half of the hash table is in use.
    if (size >= capacity >> 1) {
      capacity = capacity << 1;
      resize(capacity);
    }
    // Try to insert in the hash table first.
    int index = hashCode % capacity;
    if (table[index] == null) {
      table[index] = instruction;
    } else {
      collisions = ValueSetNode(instruction, hashCode, collisions);
    }
    size++;
  }

  HInstruction lookup(HInstruction instruction) {
    int hashCode = instruction.gvnHashCode();
    int index = hashCode % table.length;
    // Look in the hash table.
    HInstruction probe = table[index];
    if (probe != null && probe.gvnEquals(instruction)) return probe;
    // Look in the collisions list.
    for (ValueSetNode node = collisions; node != null; node = node.next) {
      if (node.hashCode == hashCode) {
        HInstruction cached = node.value;
        if (cached.gvnEquals(instruction)) return cached;
      }
    }
    return null;
  }

  void kill(int flags) {
    if (flags == 0) return;
    int depends = SideEffects.computeDependsOnFlags(flags);
    // Kill in the hash table.
    for (int index = 0, length = table.length; index < length; index++) {
      HInstruction instruction = table[index];
      if (instruction != null && instruction.sideEffects.dependsOn(depends)) {
        table[index] = null;
        size--;
      }
    }
    // Kill in the collisions list.
    ValueSetNode previous = null;
    ValueSetNode current = collisions;
    while (current != null) {
      ValueSetNode next = current.next;
      HInstruction cached = current.value;
      if (cached.sideEffects.dependsOn(depends)) {
        if (previous == null) {
          collisions = next;
        } else {
          previous.next = next;
        }
        size--;
      } else {
        previous = current;
      }
      current = next;
    }
  }

  ValueSet copy() {
    return copyTo(ValueSet(), table, collisions);
  }

  List<HInstruction> toList() {
    return copyTo(<HInstruction>[], table, collisions);
  }

  // Copy the instructions in value set defined by [table] and
  // [collisions] into [other] and returns [other]. The copy is done
  // by iterating through the hash table and the collisions list and
  // calling [:other.add:].
  static copyTo(var other, List<HInstruction> table, ValueSetNode collisions) {
    // Copy elements from the hash table.
    for (int index = 0, length = table.length; index < length; index++) {
      HInstruction instruction = table[index];
      if (instruction != null) other.add(instruction);
    }
    // Copy elements from the collision list.
    ValueSetNode current = collisions;
    while (current != null) {
      // TODO(kasperl): Maybe find a way of reusing the hash code
      // rather than recomputing it every time.
      other.add(current.value);
      current = current.next;
    }
    return other;
  }

  ValueSet intersection(ValueSet other) {
    if (size > other.size) return other.intersection(this);
    ValueSet result = ValueSet();
    // Look in the hash table.
    for (int index = 0, length = table.length; index < length; index++) {
      HInstruction instruction = table[index];
      if (instruction != null && other.lookup(instruction) != null) {
        result.add(instruction);
      }
    }
    // Look in the collision list.
    ValueSetNode current = collisions;
    while (current != null) {
      HInstruction value = current.value;
      if (other.lookup(value) != null) {
        result.add(value);
      }
      current = current.next;
    }
    return result;
  }

  void resize(int capacity) {
    var oldSize = size;
    var oldTable = table;
    var oldCollisions = collisions;
    // Reset the table with a bigger capacity.
    assert(capacity > table.length);
    size = 0;
    table = List<HInstruction>.filled(capacity, null);
    collisions = null;
    // Add the old instructions to the new table.
    copyTo(this, oldTable, oldCollisions);
    // Make sure we preserved all elements and that no resizing
    // happened as part of this resizing.
    assert(size == oldSize);
    assert(table.length == capacity);
  }
}

class ValueSetNode {
  final HInstruction value;
  final int hash;
  @override
  int get hashCode => hash;
  ValueSetNode next;
  ValueSetNode(this.value, this.hash, this.next);
}
