Have FunctionBuilder clear the ILBuilder's state in its drop().

This commit is contained in:
Dan Gohman
2017-10-19 15:13:59 -07:00
parent 9fdf44afd4
commit f4b25ff058
2 changed files with 25 additions and 5 deletions

View File

@@ -11,6 +11,10 @@ use ssa::{SSABuilder, SideEffects, Block};
use cretonne::entity::{EntityRef, EntityMap, EntitySet}; use cretonne::entity::{EntityRef, EntityMap, EntitySet};
/// Permanent structure used for translating into Cretonne IL. /// Permanent structure used for translating into Cretonne IL.
///
/// In order to reduce memory reallocations whem compiling multiple functions,
/// `ILBuilder` holds various data structures which are cleared between
/// functions, rather than dropped, preserving the underlying allocations.
pub struct ILBuilder<Variable> pub struct ILBuilder<Variable>
where where
Variable: EntityRef + Default, Variable: EntityRef + Default,
@@ -55,8 +59,8 @@ impl<Variable> ILBuilder<Variable>
where where
Variable: EntityRef + Default, Variable: EntityRef + Default,
{ {
/// Creates a ILBuilder structure. The structure is automatically cleared each time it is /// Creates a ILBuilder structure. The structure is automatically cleared after each
/// passed to a [`FunctionBuilder`](struct.FunctionBuilder.html) for creation. /// [`FunctionBuilder`](struct.FunctionBuilder.html) completes translating a function.
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
ssa: SSABuilder::new(), ssa: SSABuilder::new(),
@@ -72,6 +76,11 @@ where
self.types.clear(); self.types.clear();
self.function_args_values.clear(); self.function_args_values.clear();
} }
fn is_empty(&self) -> bool {
self.ssa.is_empty() && self.ebbs.is_empty() && self.types.is_empty() &&
self.function_args_values.is_empty()
}
} }
/// Implementation of the [`InstBuilder`](../cretonne/ir/builder/trait.InstBuilder.html) that has /// Implementation of the [`InstBuilder`](../cretonne/ir/builder/trait.InstBuilder.html) that has
@@ -216,7 +225,7 @@ where
func: &'a mut Function, func: &'a mut Function,
builder: &'a mut ILBuilder<Variable>, builder: &'a mut ILBuilder<Variable>,
) -> FunctionBuilder<'a, Variable> { ) -> FunctionBuilder<'a, Variable> {
builder.clear(); debug_assert!(builder.is_empty());
FunctionBuilder { FunctionBuilder {
func: func, func: func,
srcloc: Default::default(), srcloc: Default::default(),
@@ -491,15 +500,19 @@ where
Variable: EntityRef + Default, Variable: EntityRef + Default,
{ {
/// When a `FunctionBuilder` goes out of scope, it means that the function is fully built. /// When a `FunctionBuilder` goes out of scope, it means that the function is fully built.
/// We then proceed to check if all the `Ebb`s are filled and sealed
fn drop(&mut self) { fn drop(&mut self) {
// Check that all the `Ebb`s are filled and sealed.
debug_assert!( debug_assert!(
self.builder.ebbs.keys().all(|ebb| { self.builder.ebbs.keys().all(|ebb| {
self.builder.ebbs[ebb].pristine || self.builder.ebbs[ebb].pristine ||
(self.builder.ssa.is_sealed(ebb) && self.builder.ebbs[ebb].filled) (self.builder.ssa.is_sealed(ebb) && self.builder.ebbs[ebb].filled)
}), }),
"all blocks should be filled and sealed before dropping a FunctionBuilder" "all blocks should be filled and sealed before dropping a FunctionBuilder"
) );
// Clear the state (but preserve the allocated buffers) in preparation
// for translation another function.
self.builder.clear();
} }
} }

View File

@@ -168,6 +168,13 @@ where
debug_assert!(self.results.is_empty()); debug_assert!(self.results.is_empty());
debug_assert!(self.side_effects.is_empty()); debug_assert!(self.side_effects.is_empty());
} }
/// Tests whether an `SSABuilder` is in a cleared state.
pub fn is_empty(&self) -> bool {
self.variables.is_empty() && self.blocks.is_empty() && self.ebb_headers.is_empty() &&
self.calls.is_empty() &&
self.results.is_empty() && self.side_effects.is_empty()
}
} }
// Small enum used for clarity in some functions. // Small enum used for clarity in some functions.