Return a Result from constant_hash::probe.
When a hash table probe fails, return the index of the failed entry. This can be used to store default values in the sentinel entries.
This commit is contained in:
@@ -24,8 +24,12 @@ pub trait Table<K: Copy + Eq> {
|
|||||||
/// The provided `hash` value must have been computed from `key` using the same hash function that
|
/// The provided `hash` value must have been computed from `key` using the same hash function that
|
||||||
/// was used to construct the table.
|
/// was used to construct the table.
|
||||||
///
|
///
|
||||||
/// Returns the table index containing the found entry, or `None` if no entry could be found.
|
/// Returns `Ok(idx)` with the table index containing the found entry, or `Err(idx)` with the empty
|
||||||
pub fn probe<K: Copy + Eq, T: Table<K> + ?Sized>(table: &T, key: K, hash: usize) -> Option<usize> {
|
/// sentinel entry if no entry could be found.
|
||||||
|
pub fn probe<K: Copy + Eq, T: Table<K> + ?Sized>(table: &T,
|
||||||
|
key: K,
|
||||||
|
hash: usize)
|
||||||
|
-> Result<usize, usize> {
|
||||||
debug_assert!(table.len().is_power_of_two());
|
debug_assert!(table.len().is_power_of_two());
|
||||||
let mask = table.len() - 1;
|
let mask = table.len() - 1;
|
||||||
|
|
||||||
@@ -36,8 +40,8 @@ pub fn probe<K: Copy + Eq, T: Table<K> + ?Sized>(table: &T, key: K, hash: usize)
|
|||||||
idx &= mask;
|
idx &= mask;
|
||||||
|
|
||||||
match table.key(idx) {
|
match table.key(idx) {
|
||||||
None => return None,
|
None => return Err(idx),
|
||||||
Some(k) if k == key => return Some(idx),
|
Some(k) if k == key => return Ok(idx),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,10 +85,10 @@ impl FromStr for Opcode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match probe::<&str, [Option<Opcode>]>(&OPCODE_HASH_TABLE, s, simple_hash(s)) {
|
match probe::<&str, [Option<Opcode>]>(&OPCODE_HASH_TABLE, s, simple_hash(s)) {
|
||||||
None => Err("Unknown opcode"),
|
Err(_) => Err("Unknown opcode"),
|
||||||
// We unwrap here because probe() should have ensured that the entry
|
// We unwrap here because probe() should have ensured that the entry
|
||||||
// at this index is not None.
|
// at this index is not None.
|
||||||
Some(i) => Ok(OPCODE_HASH_TABLE[i].unwrap()),
|
Ok(i) => Ok(OPCODE_HASH_TABLE[i].unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
use ir::{Type, Opcode, InstructionData};
|
use ir::{Type, Opcode, InstructionData};
|
||||||
use isa::{Encoding, Legalize};
|
use isa::{Encoding, Legalize};
|
||||||
use constant_hash::{Table, probe};
|
use constant_hash::{Table, probe};
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
/// Level 1 hash table entry.
|
/// Level 1 hash table entry.
|
||||||
///
|
///
|
||||||
@@ -27,6 +28,14 @@ pub struct Level1Entry<OffT: Into<u32> + Copy> {
|
|||||||
pub offset: OffT,
|
pub offset: OffT,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<OffT: Into<u32> + Copy> Level1Entry<OffT> {
|
||||||
|
/// Get the level 2 table range indicated by this entry.
|
||||||
|
fn range(&self) -> Range<usize> {
|
||||||
|
let b = self.offset.into() as usize;
|
||||||
|
b..b + (1 << self.log2len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<OffT: Into<u32> + Copy> Table<Type> for [Level1Entry<OffT>] {
|
impl<OffT: Into<u32> + Copy> Table<Type> for [Level1Entry<OffT>] {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.len()
|
self.len()
|
||||||
@@ -83,20 +92,23 @@ pub fn lookup_enclist<OffT1, OffT2>(ctrl_typevar: Type,
|
|||||||
OffT2: Into<u32> + Copy
|
OffT2: Into<u32> + Copy
|
||||||
{
|
{
|
||||||
// TODO: The choice of legalization actions here is naive. This needs to be configurable.
|
// TODO: The choice of legalization actions here is naive. This needs to be configurable.
|
||||||
probe(level1_table, ctrl_typevar, ctrl_typevar.index())
|
match probe(level1_table, ctrl_typevar, ctrl_typevar.index()) {
|
||||||
.ok_or_else(|| if ctrl_typevar.lane_type().bits() > 32 {
|
Err(_) => {
|
||||||
|
// No level 1 entry for the type.
|
||||||
|
Err(if ctrl_typevar.lane_type().bits() > 32 {
|
||||||
Legalize::Narrow
|
Legalize::Narrow
|
||||||
} else {
|
} else {
|
||||||
Legalize::Expand
|
Legalize::Expand
|
||||||
})
|
})
|
||||||
.and_then(|l1idx| {
|
}
|
||||||
|
Ok(l1idx) => {
|
||||||
let l1ent = &level1_table[l1idx];
|
let l1ent = &level1_table[l1idx];
|
||||||
let l2off = l1ent.offset.into() as usize;
|
let l2tab = &level2_table[l1ent.range()];
|
||||||
let l2tab = &level2_table[l2off..l2off + (1 << l1ent.log2len)];
|
|
||||||
probe(l2tab, opcode, opcode as usize)
|
probe(l2tab, opcode, opcode as usize)
|
||||||
.map(|l2idx| l2tab[l2idx].offset.into() as usize)
|
.map(|l2idx| l2tab[l2idx].offset.into() as usize)
|
||||||
.ok_or(Legalize::Expand)
|
.map_err(|_| Legalize::Expand)
|
||||||
})
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encoding list entry.
|
/// Encoding list entry.
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ impl Builder {
|
|||||||
/// Look up a descriptor by name.
|
/// Look up a descriptor by name.
|
||||||
fn lookup(&self, name: &str) -> Result<(usize, detail::Detail)> {
|
fn lookup(&self, name: &str) -> Result<(usize, detail::Detail)> {
|
||||||
match probe(self.template, name, simple_hash(name)) {
|
match probe(self.template, name, simple_hash(name)) {
|
||||||
None => Err(Error::BadName),
|
Err(_) => Err(Error::BadName),
|
||||||
Some(entry) => {
|
Ok(entry) => {
|
||||||
let d = &self.template.descriptors[self.template.hash_table[entry] as usize];
|
let d = &self.template.descriptors[self.template.hash_table[entry] as usize];
|
||||||
Ok((d.offset as usize, d.detail))
|
Ok((d.offset as usize, d.detail))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user