< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/hashing/Hasher.java

Print this page

        

*** 28,37 **** --- 28,38 ---- import java.util.HashSet; import java.util.Optional; import java.util.Set; import java.util.TreeSet; + import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.Value;
*** 49,63 **** * @param minDensity the minimum density of the switch table. Used to determine the maximum * cardinality of the hash function * @return an optional hasher */ public static Optional<Hasher> forKeys(JavaConstant[] keys, double minDensity) { if (keys.length <= 2) { return Optional.empty(); } else { int maxCardinality = (int) Math.round(keys.length / minDensity); ! assertSorted(keys); TreeSet<Hasher> candidates = new TreeSet<>(new Comparator<Hasher>() { @Override public int compare(Hasher o1, Hasher o2) { int d = o1.cardinality - o2.cardinality; if (d != 0) { --- 50,65 ---- * @param minDensity the minimum density of the switch table. Used to determine the maximum * cardinality of the hash function * @return an optional hasher */ public static Optional<Hasher> forKeys(JavaConstant[] keys, double minDensity) { + assert checkKeyKind(keys); if (keys.length <= 2) { return Optional.empty(); } else { int maxCardinality = (int) Math.round(keys.length / minDensity); ! assert checkIfSorted(keys); TreeSet<Hasher> candidates = new TreeSet<>(new Comparator<Hasher>() { @Override public int compare(Hasher o1, Hasher o2) { int d = o1.cardinality - o2.cardinality; if (d != 0) {
*** 65,75 **** } else { return o1.effort() - o2.effort(); } } }); ! long min = keys[0].asLong(); for (HashFunction f : HashFunction.instances()) { for (int cardinality = keys.length; cardinality < maxCardinality; cardinality++) { if (isValid(keys, min, f, cardinality)) { candidates.add(new Hasher(f, cardinality, min)); break; --- 67,77 ---- } else { return o1.effort() - o2.effort(); } } }); ! int min = keys[0].asInt(); for (HashFunction f : HashFunction.instances()) { for (int cardinality = keys.length; cardinality < maxCardinality; cardinality++) { if (isValid(keys, min, f, cardinality)) { candidates.add(new Hasher(f, cardinality, min)); break;
*** 82,113 **** return Optional.of(candidates.first()); } } } ! private static void assertSorted(JavaConstant[] keys) { for (int i = 1; i < keys.length; i++) { ! assert keys[i - 1].asLong() < keys[i].asLong(); } } ! private static boolean isValid(JavaConstant[] keys, long min, HashFunction function, int cardinality) { Set<Integer> seen = new HashSet<>(keys.length); for (JavaConstant key : keys) { ! int hash = function.apply(key.asLong(), min) & (cardinality - 1); if (!seen.add(hash)) { return false; } } return true; } private final HashFunction function; private final int cardinality; ! private final long min; ! private Hasher(HashFunction function, int cardinality, long min) { this.function = function; this.cardinality = cardinality; this.min = min; } --- 84,127 ---- return Optional.of(candidates.first()); } } } ! private static boolean checkKeyKind(JavaConstant[] keys) { ! for (int i = 0; i < keys.length; i++) { ! if (keys[i].getJavaKind() != JavaKind.Int) { ! throw new AssertionError(String.format("Key at index %d is not an int: %s", i, keys[i])); ! } ! } ! return true; ! } ! ! private static boolean checkIfSorted(JavaConstant[] keys) { for (int i = 1; i < keys.length; i++) { ! if (keys[i - 1].asInt() >= keys[i].asInt()) { ! throw new AssertionError("Keys array is not sorted"); ! } } + return true; } ! private static boolean isValid(JavaConstant[] keys, int min, HashFunction function, int cardinality) { Set<Integer> seen = new HashSet<>(keys.length); for (JavaConstant key : keys) { ! int hash = function.apply(key.asInt(), min) & (cardinality - 1); if (!seen.add(hash)) { return false; } } return true; } private final HashFunction function; private final int cardinality; ! private final int min; ! private Hasher(HashFunction function, int cardinality, int min) { this.function = function; this.cardinality = cardinality; this.min = min; }
*** 115,125 **** * Applies the hash function. * * @param value the value to be hashed * @return the hash value */ ! public int hash(long value) { return function.apply(value, min) & (cardinality - 1); } /** * Applies the hash function to a lir value. --- 129,139 ---- * Applies the hash function. * * @param value the value to be hashed * @return the hash value */ ! public int hash(int value) { return function.apply(value, min) & (cardinality - 1); } /** * Applies the hash function to a lir value.
*** 127,137 **** * @param value the value to be hashed * @param gen the lir generator * @return the hashed lir value */ public Value hash(Value value, ArithmeticLIRGenerator gen) { ! Value h = function.gen(value, gen.getLIRGen().emitJavaConstant(JavaConstant.forLong(min)), gen); return gen.emitAnd(h, gen.getLIRGen().emitJavaConstant(JavaConstant.forInt(cardinality - 1))); } /** * @return the hashing effort --- 141,151 ---- * @param value the value to be hashed * @param gen the lir generator * @return the hashed lir value */ public Value hash(Value value, ArithmeticLIRGenerator gen) { ! Value h = function.gen(value, gen.getLIRGen().emitJavaConstant(JavaConstant.forInt(min)), gen); return gen.emitAnd(h, gen.getLIRGen().emitJavaConstant(JavaConstant.forInt(cardinality - 1))); } /** * @return the hashing effort
< prev index next >