From f4b25ff058f71eff2e5b15a4741dc98137811f01 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 19 Oct 2017 15:13:59 -0700 Subject: [PATCH] Have FunctionBuilder clear the ILBuilder's state in its drop(). --- lib/frontend/src/frontend.rs | 23 ++++++++++++++++++----- lib/frontend/src/ssa.rs | 7 +++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index 78f3725bce..708de69881 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -11,6 +11,10 @@ use ssa::{SSABuilder, SideEffects, Block}; use cretonne::entity::{EntityRef, EntityMap, EntitySet}; /// 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 where Variable: EntityRef + Default, @@ -55,8 +59,8 @@ impl ILBuilder where Variable: EntityRef + Default, { - /// Creates a ILBuilder structure. The structure is automatically cleared each time it is - /// passed to a [`FunctionBuilder`](struct.FunctionBuilder.html) for creation. + /// Creates a ILBuilder structure. The structure is automatically cleared after each + /// [`FunctionBuilder`](struct.FunctionBuilder.html) completes translating a function. pub fn new() -> Self { Self { ssa: SSABuilder::new(), @@ -72,6 +76,11 @@ where self.types.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 @@ -216,7 +225,7 @@ where func: &'a mut Function, builder: &'a mut ILBuilder, ) -> FunctionBuilder<'a, Variable> { - builder.clear(); + debug_assert!(builder.is_empty()); FunctionBuilder { func: func, srcloc: Default::default(), @@ -491,15 +500,19 @@ where Variable: EntityRef + Default, { /// 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) { + // Check that all the `Ebb`s are filled and sealed. debug_assert!( self.builder.ebbs.keys().all(|ebb| { self.builder.ebbs[ebb].pristine || (self.builder.ssa.is_sealed(ebb) && self.builder.ebbs[ebb].filled) }), "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(); } } diff --git a/lib/frontend/src/ssa.rs b/lib/frontend/src/ssa.rs index 600143fecc..d735caabb7 100644 --- a/lib/frontend/src/ssa.rs +++ b/lib/frontend/src/ssa.rs @@ -168,6 +168,13 @@ where debug_assert!(self.results.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.