| OLD | NEW | 
 | (Empty) | 
|    1 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file |  | 
|    2 // for details. All rights reserved. Use of this source code is governed by a |  | 
|    3 // BSD-style license that can be found in the LICENSE file. |  | 
|    4  |  | 
|    5 class ValueSet { |  | 
|    6   int size = 0; |  | 
|    7   List<HInstruction> table; |  | 
|    8   ValueSetNode collisions; |  | 
|    9   ValueSet() : table = new List<HInstruction>(8); |  | 
|   10  |  | 
|   11   bool isEmpty() => size == 0; |  | 
|   12   int get length() => size; |  | 
|   13  |  | 
|   14   void add(HInstruction instruction) { |  | 
|   15     assert(lookup(instruction) === null); |  | 
|   16     int hashCode = instruction.gvnHashCode(); |  | 
|   17     int capacity = table.length; |  | 
|   18     // Resize when half of the hash table is in use. |  | 
|   19     if (size >= capacity >> 1) { |  | 
|   20       capacity = capacity << 1; |  | 
|   21       resize(capacity); |  | 
|   22     } |  | 
|   23     // Try to insert in the hash table first. |  | 
|   24     int index = hashCode % capacity; |  | 
|   25     if (table[index] === null) { |  | 
|   26       table[index] = instruction; |  | 
|   27     } else { |  | 
|   28       collisions = new ValueSetNode(instruction, hashCode, collisions); |  | 
|   29     } |  | 
|   30     size++; |  | 
|   31   } |  | 
|   32  |  | 
|   33   HInstruction lookup(HInstruction instruction) { |  | 
|   34     int hashCode = instruction.gvnHashCode(); |  | 
|   35     int index = hashCode % table.length; |  | 
|   36     // Look in the hash table. |  | 
|   37     HInstruction probe = table[index]; |  | 
|   38     if (probe !== null && probe.gvnEquals(instruction)) return probe; |  | 
|   39     // Look in the collisions list. |  | 
|   40     for (ValueSetNode node = collisions; node !== null; node = node.next) { |  | 
|   41       if (node.hashCode == hashCode) { |  | 
|   42         HInstruction cached = node.value; |  | 
|   43         if (cached.gvnEquals(instruction)) return cached; |  | 
|   44       } |  | 
|   45     } |  | 
|   46     return null; |  | 
|   47   } |  | 
|   48  |  | 
|   49   void kill(int flags) { |  | 
|   50     int depends = HInstruction.computeDependsOnFlags(flags); |  | 
|   51     // Kill in the hash table. |  | 
|   52     for (int index = 0, length = table.length; index < length; index++) { |  | 
|   53       HInstruction instruction = table[index]; |  | 
|   54       if (instruction !== null && (instruction.flags & depends) != 0) { |  | 
|   55         table[index] = null; |  | 
|   56         size--; |  | 
|   57       } |  | 
|   58     } |  | 
|   59     // Kill in the collisions list. |  | 
|   60     ValueSetNode previous = null; |  | 
|   61     ValueSetNode current = collisions; |  | 
|   62     while (current !== null) { |  | 
|   63       ValueSetNode next = current.next; |  | 
|   64       HInstruction cached = current.value; |  | 
|   65       if ((cached.flags & depends) != 0) { |  | 
|   66         if (previous === null) { |  | 
|   67           collisions = next; |  | 
|   68         } else { |  | 
|   69           previous.next = next; |  | 
|   70         } |  | 
|   71         size--; |  | 
|   72       } else { |  | 
|   73         previous = current; |  | 
|   74       } |  | 
|   75       current = next; |  | 
|   76     } |  | 
|   77   } |  | 
|   78  |  | 
|   79   ValueSet copy() { |  | 
|   80     return copyTo(new ValueSet(), table, collisions); |  | 
|   81   } |  | 
|   82  |  | 
|   83   List<HInstruction> toList() { |  | 
|   84     return copyTo(<HInstruction>[], table, collisions); |  | 
|   85   } |  | 
|   86  |  | 
|   87   // Copy the instructions in value set defined by [table] and |  | 
|   88   // [collisions] into [other] and returns [other]. The copy is done |  | 
|   89   // by iterating through the hash table and the collisions list and |  | 
|   90   // calling [:other.add:]. |  | 
|   91   static copyTo(var other, List<HInstruction> table, ValueSetNode collisions) { |  | 
|   92     // Copy elements from the hash table. |  | 
|   93     for (int index = 0, length = table.length; index < length; index++) { |  | 
|   94       HInstruction instruction = table[index]; |  | 
|   95       if (instruction !== null) other.add(instruction); |  | 
|   96     } |  | 
|   97     // Copy elements from the collision list. |  | 
|   98     ValueSetNode current = collisions; |  | 
|   99     while (current !== null) { |  | 
|  100       // TODO(kasperl): Maybe find a way of reusing the hash code |  | 
|  101       // rather than recomputing it every time. |  | 
|  102       other.add(current.value); |  | 
|  103       current = current.next; |  | 
|  104     } |  | 
|  105     return other; |  | 
|  106   } |  | 
|  107  |  | 
|  108   ValueSet intersection(ValueSet other) { |  | 
|  109     if (size > other.size) return other.intersection(this); |  | 
|  110     ValueSet result = new ValueSet(); |  | 
|  111     // Look in the hash table. |  | 
|  112     for (int index = 0, length = table.length; index < length; index++) { |  | 
|  113       HInstruction instruction = table[index]; |  | 
|  114       if (instruction !== null && other.lookup(instruction) !== null) { |  | 
|  115         result.add(instruction); |  | 
|  116       } |  | 
|  117     } |  | 
|  118     // Look in the collision list. |  | 
|  119     ValueSetNode current = collisions; |  | 
|  120     while (current !== null) { |  | 
|  121       HInstruction value = current.value; |  | 
|  122       if (other.lookup(value) !== null) { |  | 
|  123         result.add(value); |  | 
|  124       } |  | 
|  125       current = current.next; |  | 
|  126     } |  | 
|  127     return result; |  | 
|  128   } |  | 
|  129  |  | 
|  130   void resize(int capacity) { |  | 
|  131     var oldSize = size; |  | 
|  132     var oldTable = table; |  | 
|  133     var oldCollisions = collisions; |  | 
|  134     // Reset the table with a bigger capacity. |  | 
|  135     assert(capacity > table.length); |  | 
|  136     size = 0; |  | 
|  137     table = new List<HInstruction>(capacity); |  | 
|  138     collisions = null; |  | 
|  139     // Add the old instructions to the new table. |  | 
|  140     copyTo(this, oldTable, oldCollisions); |  | 
|  141     // Make sure we preserved all elements and that no resizing |  | 
|  142     // happened as part of this resizing. |  | 
|  143     assert(size == oldSize); |  | 
|  144     assert(table.length == capacity); |  | 
|  145   } |  | 
|  146 } |  | 
|  147  |  | 
|  148 class ValueSetNode { |  | 
|  149   final HInstruction value; |  | 
|  150   final int hashCode; |  | 
|  151   ValueSetNode next; |  | 
|  152   ValueSetNode(this.value, this.hashCode, this.next); |  | 
|  153 } |  | 
| OLD | NEW |