-
Notifications
You must be signed in to change notification settings - Fork 26
Description
Similar to the discussion here, to associate arbitrary data with Operations (or Types) in analyses / transforms, we currently need to use a hash table (such as FxHashMap<Ptr<Operation>, _>).
Providing an aux or scratch field within Operation itself allows using the field as an index into an array (i.e., faster than hashing) that can contain any data.
A safe way of providing such a field, so that different analyses or transforms do not end up reading a stale value from a previous pass, is to associate each (dynamic) user (an analysis or transform instance) of the field with an aux_field_user_id, that is unique to that instance of the pass. A sample implementation:
#[derive(Default)]
pub struct AuxFieldUserId(usize);
Context {
aux_user_count: usize,
...
}
impl Context {
pub fn get_new_aux_user_id(&mut self) -> AuxFieldUserId {
self.aux_user_count += 1;
AuxFieldUserId(self.aux_user_count)
}
}
Operation {
aux_data: (AuxFieldUserId, usize)
...
}
impl Operation {
pub fn get_aux_data(&self, aux_user_id: AuxFieldUserId) -> Option<usize> {
(self.aux_data.0 == aux_user_id).then_some(self.aux_data.1)
}
pub fn set_aux_data(&self, aux_user_id: AuxFieldUserId, data: usize) {
self.aux_data = (data, aux_user_id);
}
}
Every pass (analysis or transform), each time it runs, will call Context::get_new_aux_user_id and use that aux_user_id each time it sets or gets the aux data.