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