Skip to content

Commit

Permalink
Change liveness_set to RegionValues to reduce memory usage.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtwco committed Jul 13, 2018
1 parent bce32b5 commit 8081609
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 121 deletions.
47 changes: 41 additions & 6 deletions src/librustc_data_structures/bitvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,10 @@ where
}

impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
/// Create a new `rows x columns` matrix, initially empty.
pub fn new(rows: R, _columns: C) -> SparseBitMatrix<R, C> {
SparseBitMatrix {
vector: IndexVec::from_elem_n(SparseBitSet::new(), rows.index()),
/// Create a new empty sparse bit matrix with no rows or columns.
pub fn new() -> Self {
Self {
vector: IndexVec::new(),
}
}

Expand All @@ -293,15 +293,23 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
///
/// Returns true if this changed the matrix, and false otherwise.
pub fn add(&mut self, row: R, column: C) -> bool {
self.vector[row].insert(column)
if let None = self.vector.get(row) {
self.vector.push(SparseBitSet::new());
}

if let Some(row) = self.vector.get_mut(row) {
row.insert(column)
} else {
false
}
}

/// Do the bits from `row` contain `column`? Put another way, is
/// the matrix cell at `(row, column)` true? Put yet another way,
/// if the matrix represents (transitive) reachability, can
/// `row` reach `column`?
pub fn contains(&self, row: R, column: C) -> bool {
self.vector[row].contains(column)
self.vector.get(row).map_or(false, |r| r.contains(column))
}

/// Add the bits from row `read` to the bits from row `write`,
Expand All @@ -325,6 +333,14 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
changed
}

/// Merge a row, `from`, into the `into` row.
pub fn merge_into(&mut self, into: R, from: &SparseBitSet<C>) -> bool {
match self.vector.get_mut(into) {
Some(row) => row.merge_into(from),
None => false,
}
}

/// True if `sub` is a subset of `sup`
pub fn is_subset(&self, sub: R, sup: R) -> bool {
sub == sup || {
Expand All @@ -336,11 +352,21 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
}
}

/// Number of elements in the matrix.
pub fn len(&self) -> usize {
self.vector.len()
}

/// Iterates through all the columns set to true in a given row of
/// the matrix.
pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
self.vector[row].iter()
}

/// Iterates through each row and the accompanying bit set.
pub fn iter_enumerated<'a>(&'a self) -> impl Iterator<Item = (R, &'a SparseBitSet<C>)> + 'a {
self.vector.iter_enumerated()
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -445,6 +471,15 @@ impl<I: Idx> SparseBitSet<I> {
}
}

/// Merge two sparse bit sets.
pub fn merge_into(&mut self, from: &SparseBitSet<I>) -> bool {
let mut changed = false;
for read_chunk in from.chunks() {
changed = changed | self.insert_chunk(read_chunk).any();
}
changed
}

pub fn remove_chunk(&mut self, chunk: SparseChunk<I>) -> SparseChunk<I> {
if chunk.bits == 0 {
return chunk;
Expand Down
49 changes: 24 additions & 25 deletions src/librustc_mir/borrow_check/nll/constraint_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
use borrow_check::location::LocationTable;
use borrow_check::nll::ToRegionVid;
use borrow_check::nll::facts::AllFacts;
use borrow_check::nll::region_infer::RegionInferenceContext;
use borrow_check::nll::region_infer::{RegionElement, RegionInferenceContext};
use rustc::infer::InferCtxt;
use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor;
Expand All @@ -30,7 +30,6 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
location_table: &LocationTable,
mir: &Mir<'tcx>,
borrow_set: &BorrowSet<'tcx>,
liveness_set_from_typeck: &[(ty::Region<'tcx>, Location)],
) {
let mut cg = ConstraintGeneration {
borrow_set,
Expand All @@ -40,7 +39,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
all_facts,
};

cg.add_region_liveness_constraints_from_type_check(liveness_set_from_typeck);
cg.add_region_liveness_constraints_from_type_check();

for (bb, data) in mir.basic_blocks().iter_enumerated() {
cg.visit_basic_block_data(bb, data);
Expand Down Expand Up @@ -191,37 +190,37 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
/// The MIR type checker generates region liveness constraints
/// that we also have to respect.
fn add_region_liveness_constraints_from_type_check(
&mut self,
liveness_set: &[(ty::Region<'tcx>, Location)],
) {
debug!(
"add_region_liveness_constraints_from_type_check(liveness_set={} items)",
liveness_set.len(),
);

fn add_region_liveness_constraints_from_type_check(&mut self) {
let ConstraintGeneration {
regioncx,
location_table,
all_facts,
..
} = self;

for (region, location) in liveness_set {
debug!("generate: {:#?} is live at {:#?}", region, location);
let region_vid = regioncx.to_region_vid(region);
regioncx.add_live_element(region_vid, *location);
}
debug!(
"add_region_liveness_constraints_from_type_check(liveness_constraints={} items)",
regioncx.number_of_liveness_constraints(),
);

if let Some(all_facts) = all_facts {
all_facts
.region_live_at
.extend(liveness_set.into_iter().flat_map(|(region, location)| {
let r = regioncx.to_region_vid(region);
let p1 = location_table.start_index(*location);
let p2 = location_table.mid_index(*location);
iter::once((r, p1)).chain(iter::once((r, p2)))
}));
for (r, _) in regioncx.liveness_constraints() {
all_facts
.region_live_at
.extend(regioncx.elements_contained_in(r)
.filter_map(|region_element| {
if let RegionElement::Location(location) = region_element {
Some(location)
} else {
None
}
})
.flat_map(|location| {
let p1 = location_table.start_index(location);
let p2 = location_table.mid_index(location);
iter::once((r, p1)).chain(iter::once((r, p2)))
}));
}
}
}

Expand Down
9 changes: 7 additions & 2 deletions src/librustc_mir/borrow_check/nll/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
use borrow_check::location::{LocationIndex, LocationTable};
use borrow_check::nll::facts::AllFactsExt;
use borrow_check::nll::type_check::MirTypeckRegionConstraints;
use borrow_check::nll::region_infer::RegionValueElements;
use dataflow::indexes::BorrowIndex;
use dataflow::move_paths::MoveData;
use dataflow::FlowAtLocation;
Expand Down Expand Up @@ -99,6 +100,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
None
};

let elements = &Rc::new(RegionValueElements::new(mir, universal_regions.len()));

// Run the MIR type-checker.
let liveness = &LivenessResults::compute(mir);
let constraint_sets = type_check::type_check(
Expand All @@ -113,6 +116,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
&mut all_facts,
flow_inits,
move_data,
elements,
);

if let Some(all_facts) = &mut all_facts {
Expand All @@ -126,7 +130,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
// base constraints generated by the type-check.
let var_origins = infcx.take_region_var_origins();
let MirTypeckRegionConstraints {
liveness_set,
liveness_constraints,
outlives_constraints,
type_tests,
} = constraint_sets;
Expand All @@ -136,6 +140,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
mir,
outlives_constraints,
type_tests,
liveness_constraints,
elements,
);

// Generate various additional constraints.
Expand All @@ -146,7 +152,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
location_table,
&mir,
borrow_set,
&liveness_set,
);
invalidation::generate_invalidates(
infcx,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
return;
}

for constraint in self.constraint_graph.outgoing_edges(current_region) {
assert_eq!(self.constraints[constraint].sup, current_region);
stack.push(constraint);
self.find_constraint_paths_between_regions_helper(
from_region,
self.constraints[constraint].sub,
target_test,
visited,
stack,
results,
);
stack.pop();
}
}

/// This function will return true if a constraint is interesting and false if a constraint
Expand Down
53 changes: 35 additions & 18 deletions src/librustc_mir/borrow_check/nll/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use super::universal_regions::UniversalRegions;
use borrow_check::nll::constraints::{
ConstraintIndex, ConstraintSccIndex, ConstraintSet, OutlivesConstraint,
};
use borrow_check::nll::constraints::graph::ConstraintGraph;
use borrow_check::nll::region_infer::values::ToElementIndex;
use borrow_check::nll::type_check::Locations;
use rustc::hir::def_id::DefId;
Expand All @@ -27,6 +26,7 @@ use rustc::mir::{
};
use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
use rustc::util::common;
use rustc_data_structures::bitvec::SparseBitSet;
use rustc_data_structures::graph::scc::Sccs;
use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
use rustc_data_structures::indexed_vec::IndexVec;
Expand All @@ -38,7 +38,7 @@ mod dump_mir;
mod error_reporting;
mod graphviz;
mod values;
use self::values::{RegionValueElements, RegionValues};
crate use self::values::{RegionElement, RegionElementIndex, RegionValueElements, RegionValues};

use super::ToRegionVid;

Expand All @@ -61,13 +61,8 @@ pub struct RegionInferenceContext<'tcx> {
/// The outlives constraints computed by the type-check.
constraints: Rc<ConstraintSet>,

/// The constraint-set, but in graph form, making it easy to traverse
/// the constraints adjacent to a particular region. Used to construct
/// the SCC (see `constraint_sccs`) and for error reporting.
constraint_graph: Rc<ConstraintGraph>,

/// The SCC computed from `constraints` and
/// `constraint_graph`. Used to compute the values of each region.
/// The SCC computed from `constraints` and the constraint graph. Used to compute the values
/// of each region.
constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,

/// The final inferred values of the region variables; we compute
Expand Down Expand Up @@ -207,15 +202,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn new(
var_infos: VarInfos,
universal_regions: UniversalRegions<'tcx>,
mir: &Mir<'tcx>,
_mir: &Mir<'tcx>,
outlives_constraints: ConstraintSet,
type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: RegionValues<RegionVid>,
elements: &Rc<RegionValueElements>,
) -> Self {
let universal_regions = Rc::new(universal_regions);
let num_region_variables = var_infos.len();
let num_universal_regions = universal_regions.len();

let elements = &Rc::new(RegionValueElements::new(mir, num_universal_regions));

// Create a RegionDefinition for each inference variable.
let definitions: IndexVec<_, _> = var_infos
Expand All @@ -227,15 +220,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let constraint_graph = Rc::new(constraints.graph(definitions.len()));
let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph));

let scc_values = RegionValues::new(elements, constraint_sccs.num_sccs());
let mut scc_values = RegionValues::new(elements);

for (region, location_set) in liveness_constraints.iter_enumerated() {
let scc = constraint_sccs.scc(region);
scc_values.merge_into(scc, location_set);
}

let mut result = Self {
definitions,
elements: elements.clone(),
liveness_constraints: RegionValues::new(elements, num_region_variables),
liveness_constraints,
constraints,
constraint_sccs,
constraint_graph,
scc_values,
type_tests,
universal_regions,
Expand Down Expand Up @@ -304,6 +301,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.definitions.indices()
}

/// Iterates through each row and the accompanying bit set.
pub fn liveness_constraints<'a>(
&'a self
) -> impl Iterator<Item = (RegionVid, &'a SparseBitSet<RegionElementIndex>)> + 'a {
self.liveness_constraints.iter_enumerated()
}

/// Number of liveness constaints in region inference context.
pub fn number_of_liveness_constraints(&self) -> usize {
self.liveness_constraints.len()
}

/// Returns all the elements contained in a given region's value.
crate fn elements_contained_in<'a>(
&'a self,
r: RegionVid,
) -> impl Iterator<Item = RegionElement> + 'a {
self.liveness_constraints.elements_contained_in(r)
}

/// Given a universal region in scope on the MIR, returns the
/// corresponding index.
///
Expand Down Expand Up @@ -414,7 +431,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
constraints
});

// To propagate constriants, we walk the DAG induced by the
// To propagate constraints, we walk the DAG induced by the
// SCC. For each SCC, we visit its successors and compute
// their values, then we union all those values to get our
// own.
Expand Down
Loading

0 comments on commit 8081609

Please sign in to comment.