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

// @dart = 2.10

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() {
    List<HInstruction> result = [];
    // Copy elements from the hash table.
    for (final instruction in table) {
      if (instruction != null) result.add(instruction);
    }
    // Copy elements from the collision list.
    for (var current = collisions; current != null; current = current.next) {
      result.add(current.value);
    }
    return result;
  }

  // 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 ValueSet copyTo(
      ValueSet other, List<HInstruction> table, ValueSetNode collisions) {
    // Copy elements from the hash table.
    for (final instruction in table) {
      if (instruction != null) other.add(instruction);
    }
    // Copy elements from the collision list.
    for (var current = collisions; current != null; current = current.next) {
      // TODO(kasperl): Maybe find a way of reusing the hash code
      // rather than recomputing it every time.
      other.add(current.value);
    }
    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);
}
