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