intern common tag names

This commit is contained in:
Folkert 2022-03-20 15:30:47 +01:00
parent 00ef997be3
commit 38c2710fc5
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
2 changed files with 62 additions and 21 deletions

View file

@ -1850,6 +1850,29 @@ fn find_tag_name_run<T>(slice: &[(TagName, T)], subs: &mut Subs) -> Option<SubsS
result
}
#[inline(always)]
fn register_tag_arguments<'a>(
subs: &mut Subs,
rank: Rank,
pools: &mut Pools,
arena: &'_ bumpalo::Bump,
stack: &mut bumpalo::collections::Vec<'_, TypeToVar<'a>>,
arguments: &'a [Type],
) -> VariableSubsSlice {
if arguments.is_empty() {
VariableSubsSlice::default()
} else {
let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len());
let it = (new_variables.indices()).zip(arguments);
for (target_index, argument) in it {
let var = RegisterVariable::with_stack(subs, rank, pools, arena, argument, stack);
subs.variables[target_index] = var;
}
new_variables
}
}
/// Assumes that the tags are sorted and there are no duplicates!
fn insert_tags_fast_path<'a>(
subs: &mut Subs,
@ -1859,23 +1882,35 @@ fn insert_tags_fast_path<'a>(
tags: &'a [(TagName, Vec<Type>)],
stack: &mut bumpalo::collections::Vec<'_, TypeToVar<'a>>,
) -> UnionTags {
let new_variable_slices = SubsSlice::reserve_variable_slices(subs, tags.len());
if let [(TagName::Global(tag_name), arguments)] = tags {
let variable_slice = register_tag_arguments(subs, rank, pools, arena, stack, arguments);
let new_variable_slices =
SubsSlice::extend_new(&mut subs.variable_slices, [variable_slice]);
macro_rules! subs_tag_name {
($tag_name_slice:expr) => {
return UnionTags::from_slices($tag_name_slice, new_variable_slices)
};
}
match tag_name.as_str() {
"Ok" => subs_tag_name!(Subs::TAG_NAME_OK.as_slice()),
"Err" => subs_tag_name!(Subs::TAG_NAME_ERR.as_slice()),
"InvalidNumStr" => subs_tag_name!(Subs::TAG_NAME_INVALID_NUM_STR.as_slice()),
"BadUtf8" => subs_tag_name!(Subs::TAG_NAME_BAD_UTF_8.as_slice()),
"OutOfBounds" => subs_tag_name!(Subs::TAG_NAME_OUT_OF_BOUNDS.as_slice()),
_other => {}
}
}
let new_variable_slices = SubsSlice::reserve_variable_slices(subs, tags.len());
match find_tag_name_run(tags, subs) {
Some(new_tag_names) => {
let it = (new_variable_slices.indices()).zip(tags);
for (variable_slice_index, (_, arguments)) in it {
// turn the arguments into variables
let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len());
let it = (new_variables.indices()).zip(arguments);
for (target_index, argument) in it {
let var =
RegisterVariable::with_stack(subs, rank, pools, arena, argument, stack);
subs.variables[target_index] = var;
}
subs.variable_slices[variable_slice_index] = new_variables;
subs.variable_slices[variable_slice_index] =
register_tag_arguments(subs, rank, pools, arena, stack, arguments);
}
UnionTags::from_slices(new_tag_names, new_variable_slices)
@ -1888,16 +1923,9 @@ fn insert_tags_fast_path<'a>(
.zip(tags);
for ((variable_slice_index, tag_name_index), (tag_name, arguments)) in it {
// turn the arguments into variables
let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len());
let it = (new_variables.indices()).zip(arguments);
for (target_index, argument) in it {
let var =
RegisterVariable::with_stack(subs, rank, pools, arena, argument, stack);
subs.variables[target_index] = var;
}
subs.variable_slices[variable_slice_index] =
register_tag_arguments(subs, rank, pools, arena, stack, arguments);
subs.variable_slices[variable_slice_index] = new_variables;
subs.tag_names[tag_name_index] = tag_name.clone();
}

View file

@ -331,7 +331,7 @@ impl SubsSlice<TagName> {
}
impl<T> SubsIndex<T> {
pub fn new(start: u32) -> Self {
pub const fn new(start: u32) -> Self {
Self {
index: start,
_marker: std::marker::PhantomData,
@ -345,6 +345,10 @@ impl<T> SubsIndex<T> {
index
}
pub const fn as_slice(self) -> SubsSlice<T> {
SubsSlice::new(self.index, 1)
}
}
impl<T> IntoIterator for SubsSlice<T> {
@ -1291,9 +1295,14 @@ fn define_float_types(subs: &mut Subs) {
impl Subs {
pub const RESULT_TAG_NAMES: SubsSlice<TagName> = SubsSlice::new(0, 2);
pub const TAG_NAME_ERR: SubsIndex<TagName> = SubsIndex::new(0);
pub const TAG_NAME_OK: SubsIndex<TagName> = SubsIndex::new(1);
pub const NUM_AT_NUM: SubsSlice<TagName> = SubsSlice::new(2, 1);
pub const NUM_AT_INTEGER: SubsSlice<TagName> = SubsSlice::new(3, 1);
pub const NUM_AT_FLOATINGPOINT: SubsSlice<TagName> = SubsSlice::new(4, 1);
pub const TAG_NAME_INVALID_NUM_STR: SubsIndex<TagName> = SubsIndex::new(5);
pub const TAG_NAME_BAD_UTF_8: SubsIndex<TagName> = SubsIndex::new(6);
pub const TAG_NAME_OUT_OF_BOUNDS: SubsIndex<TagName> = SubsIndex::new(7);
pub fn new() -> Self {
Self::with_capacity(0)
@ -1311,6 +1320,10 @@ impl Subs {
tag_names.push(TagName::Private(Symbol::NUM_AT_INTEGER));
tag_names.push(TagName::Private(Symbol::NUM_AT_FLOATINGPOINT));
tag_names.push(TagName::Global("InvalidNumStr".into()));
tag_names.push(TagName::Global("BadUtf8".into()));
tag_names.push(TagName::Global("OutOfBounds".into()));
let mut subs = Subs {
utable: UnificationTable::default(),
variables: Vec::new(),