Skip to content

Commit 8081609

Browse files
committed
Change liveness_set to RegionValues to reduce memory usage.
1 parent bce32b5 commit 8081609

File tree

8 files changed

+186
-121
lines changed

8 files changed

+186
-121
lines changed

src/librustc_data_structures/bitvec.rs

+41-6
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,10 @@ where
281281
}
282282

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

@@ -293,15 +293,23 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
293293
///
294294
/// Returns true if this changed the matrix, and false otherwise.
295295
pub fn add(&mut self, row: R, column: C) -> bool {
296-
self.vector[row].insert(column)
296+
if let None = self.vector.get(row) {
297+
self.vector.push(SparseBitSet::new());
298+
}
299+
300+
if let Some(row) = self.vector.get_mut(row) {
301+
row.insert(column)
302+
} else {
303+
false
304+
}
297305
}
298306

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

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

336+
/// Merge a row, `from`, into the `into` row.
337+
pub fn merge_into(&mut self, into: R, from: &SparseBitSet<C>) -> bool {
338+
match self.vector.get_mut(into) {
339+
Some(row) => row.merge_into(from),
340+
None => false,
341+
}
342+
}
343+
328344
/// True if `sub` is a subset of `sup`
329345
pub fn is_subset(&self, sub: R, sup: R) -> bool {
330346
sub == sup || {
@@ -336,11 +352,21 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
336352
}
337353
}
338354

355+
/// Number of elements in the matrix.
356+
pub fn len(&self) -> usize {
357+
self.vector.len()
358+
}
359+
339360
/// Iterates through all the columns set to true in a given row of
340361
/// the matrix.
341362
pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
342363
self.vector[row].iter()
343364
}
365+
366+
/// Iterates through each row and the accompanying bit set.
367+
pub fn iter_enumerated<'a>(&'a self) -> impl Iterator<Item = (R, &'a SparseBitSet<C>)> + 'a {
368+
self.vector.iter_enumerated()
369+
}
344370
}
345371

346372
#[derive(Clone, Debug)]
@@ -445,6 +471,15 @@ impl<I: Idx> SparseBitSet<I> {
445471
}
446472
}
447473

474+
/// Merge two sparse bit sets.
475+
pub fn merge_into(&mut self, from: &SparseBitSet<I>) -> bool {
476+
let mut changed = false;
477+
for read_chunk in from.chunks() {
478+
changed = changed | self.insert_chunk(read_chunk).any();
479+
}
480+
changed
481+
}
482+
448483
pub fn remove_chunk(&mut self, chunk: SparseChunk<I>) -> SparseChunk<I> {
449484
if chunk.bits == 0 {
450485
return chunk;

src/librustc_mir/borrow_check/nll/constraint_generation.rs

+24-25
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
1212
use borrow_check::location::LocationTable;
1313
use borrow_check::nll::ToRegionVid;
1414
use borrow_check::nll::facts::AllFacts;
15-
use borrow_check::nll::region_infer::RegionInferenceContext;
15+
use borrow_check::nll::region_infer::{RegionElement, RegionInferenceContext};
1616
use rustc::infer::InferCtxt;
1717
use rustc::mir::visit::TyContext;
1818
use rustc::mir::visit::Visitor;
@@ -30,7 +30,6 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
3030
location_table: &LocationTable,
3131
mir: &Mir<'tcx>,
3232
borrow_set: &BorrowSet<'tcx>,
33-
liveness_set_from_typeck: &[(ty::Region<'tcx>, Location)],
3433
) {
3534
let mut cg = ConstraintGeneration {
3635
borrow_set,
@@ -40,7 +39,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
4039
all_facts,
4140
};
4241

43-
cg.add_region_liveness_constraints_from_type_check(liveness_set_from_typeck);
42+
cg.add_region_liveness_constraints_from_type_check();
4443

4544
for (bb, data) in mir.basic_blocks().iter_enumerated() {
4645
cg.visit_basic_block_data(bb, data);
@@ -191,37 +190,37 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
191190
impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
192191
/// The MIR type checker generates region liveness constraints
193192
/// that we also have to respect.
194-
fn add_region_liveness_constraints_from_type_check(
195-
&mut self,
196-
liveness_set: &[(ty::Region<'tcx>, Location)],
197-
) {
198-
debug!(
199-
"add_region_liveness_constraints_from_type_check(liveness_set={} items)",
200-
liveness_set.len(),
201-
);
202-
193+
fn add_region_liveness_constraints_from_type_check(&mut self) {
203194
let ConstraintGeneration {
204195
regioncx,
205196
location_table,
206197
all_facts,
207198
..
208199
} = self;
209200

210-
for (region, location) in liveness_set {
211-
debug!("generate: {:#?} is live at {:#?}", region, location);
212-
let region_vid = regioncx.to_region_vid(region);
213-
regioncx.add_live_element(region_vid, *location);
214-
}
201+
debug!(
202+
"add_region_liveness_constraints_from_type_check(liveness_constraints={} items)",
203+
regioncx.number_of_liveness_constraints(),
204+
);
215205

216206
if let Some(all_facts) = all_facts {
217-
all_facts
218-
.region_live_at
219-
.extend(liveness_set.into_iter().flat_map(|(region, location)| {
220-
let r = regioncx.to_region_vid(region);
221-
let p1 = location_table.start_index(*location);
222-
let p2 = location_table.mid_index(*location);
223-
iter::once((r, p1)).chain(iter::once((r, p2)))
224-
}));
207+
for (r, _) in regioncx.liveness_constraints() {
208+
all_facts
209+
.region_live_at
210+
.extend(regioncx.elements_contained_in(r)
211+
.filter_map(|region_element| {
212+
if let RegionElement::Location(location) = region_element {
213+
Some(location)
214+
} else {
215+
None
216+
}
217+
})
218+
.flat_map(|location| {
219+
let p1 = location_table.start_index(location);
220+
let p2 = location_table.mid_index(location);
221+
iter::once((r, p1)).chain(iter::once((r, p2)))
222+
}));
223+
}
225224
}
226225
}
227226

src/librustc_mir/borrow_check/nll/mod.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
1212
use borrow_check::location::{LocationIndex, LocationTable};
1313
use borrow_check::nll::facts::AllFactsExt;
1414
use borrow_check::nll::type_check::MirTypeckRegionConstraints;
15+
use borrow_check::nll::region_infer::RegionValueElements;
1516
use dataflow::indexes::BorrowIndex;
1617
use dataflow::move_paths::MoveData;
1718
use dataflow::FlowAtLocation;
@@ -99,6 +100,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
99100
None
100101
};
101102

103+
let elements = &Rc::new(RegionValueElements::new(mir, universal_regions.len()));
104+
102105
// Run the MIR type-checker.
103106
let liveness = &LivenessResults::compute(mir);
104107
let constraint_sets = type_check::type_check(
@@ -113,6 +116,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
113116
&mut all_facts,
114117
flow_inits,
115118
move_data,
119+
elements,
116120
);
117121

118122
if let Some(all_facts) = &mut all_facts {
@@ -126,7 +130,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
126130
// base constraints generated by the type-check.
127131
let var_origins = infcx.take_region_var_origins();
128132
let MirTypeckRegionConstraints {
129-
liveness_set,
133+
liveness_constraints,
130134
outlives_constraints,
131135
type_tests,
132136
} = constraint_sets;
@@ -136,6 +140,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
136140
mir,
137141
outlives_constraints,
138142
type_tests,
143+
liveness_constraints,
144+
elements,
139145
);
140146

141147
// Generate various additional constraints.
@@ -146,7 +152,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
146152
location_table,
147153
&mir,
148154
borrow_set,
149-
&liveness_set,
150155
);
151156
invalidation::generate_invalidates(
152157
infcx,

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

-14
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9494
}
9595
return;
9696
}
97-
98-
for constraint in self.constraint_graph.outgoing_edges(current_region) {
99-
assert_eq!(self.constraints[constraint].sup, current_region);
100-
stack.push(constraint);
101-
self.find_constraint_paths_between_regions_helper(
102-
from_region,
103-
self.constraints[constraint].sub,
104-
target_test,
105-
visited,
106-
stack,
107-
results,
108-
);
109-
stack.pop();
110-
}
11197
}
11298

11399
/// This function will return true if a constraint is interesting and false if a constraint

src/librustc_mir/borrow_check/nll/region_infer/mod.rs

+35-18
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use super::universal_regions::UniversalRegions;
1212
use borrow_check::nll::constraints::{
1313
ConstraintIndex, ConstraintSccIndex, ConstraintSet, OutlivesConstraint,
1414
};
15-
use borrow_check::nll::constraints::graph::ConstraintGraph;
1615
use borrow_check::nll::region_infer::values::ToElementIndex;
1716
use borrow_check::nll::type_check::Locations;
1817
use rustc::hir::def_id::DefId;
@@ -27,6 +26,7 @@ use rustc::mir::{
2726
};
2827
use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
2928
use rustc::util::common;
29+
use rustc_data_structures::bitvec::SparseBitSet;
3030
use rustc_data_structures::graph::scc::Sccs;
3131
use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
3232
use rustc_data_structures::indexed_vec::IndexVec;
@@ -38,7 +38,7 @@ mod dump_mir;
3838
mod error_reporting;
3939
mod graphviz;
4040
mod values;
41-
use self::values::{RegionValueElements, RegionValues};
41+
crate use self::values::{RegionElement, RegionElementIndex, RegionValueElements, RegionValues};
4242

4343
use super::ToRegionVid;
4444

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

64-
/// The constraint-set, but in graph form, making it easy to traverse
65-
/// the constraints adjacent to a particular region. Used to construct
66-
/// the SCC (see `constraint_sccs`) and for error reporting.
67-
constraint_graph: Rc<ConstraintGraph>,
68-
69-
/// The SCC computed from `constraints` and
70-
/// `constraint_graph`. Used to compute the values of each region.
64+
/// The SCC computed from `constraints` and the constraint graph. Used to compute the values
65+
/// of each region.
7166
constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
7267

7368
/// The final inferred values of the region variables; we compute
@@ -207,15 +202,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
207202
pub(crate) fn new(
208203
var_infos: VarInfos,
209204
universal_regions: UniversalRegions<'tcx>,
210-
mir: &Mir<'tcx>,
205+
_mir: &Mir<'tcx>,
211206
outlives_constraints: ConstraintSet,
212207
type_tests: Vec<TypeTest<'tcx>>,
208+
liveness_constraints: RegionValues<RegionVid>,
209+
elements: &Rc<RegionValueElements>,
213210
) -> Self {
214211
let universal_regions = Rc::new(universal_regions);
215-
let num_region_variables = var_infos.len();
216-
let num_universal_regions = universal_regions.len();
217-
218-
let elements = &Rc::new(RegionValueElements::new(mir, num_universal_regions));
219212

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

230-
let scc_values = RegionValues::new(elements, constraint_sccs.num_sccs());
223+
let mut scc_values = RegionValues::new(elements);
224+
225+
for (region, location_set) in liveness_constraints.iter_enumerated() {
226+
let scc = constraint_sccs.scc(region);
227+
scc_values.merge_into(scc, location_set);
228+
}
231229

232230
let mut result = Self {
233231
definitions,
234232
elements: elements.clone(),
235-
liveness_constraints: RegionValues::new(elements, num_region_variables),
233+
liveness_constraints,
236234
constraints,
237235
constraint_sccs,
238-
constraint_graph,
239236
scc_values,
240237
type_tests,
241238
universal_regions,
@@ -304,6 +301,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
304301
self.definitions.indices()
305302
}
306303

304+
/// Iterates through each row and the accompanying bit set.
305+
pub fn liveness_constraints<'a>(
306+
&'a self
307+
) -> impl Iterator<Item = (RegionVid, &'a SparseBitSet<RegionElementIndex>)> + 'a {
308+
self.liveness_constraints.iter_enumerated()
309+
}
310+
311+
/// Number of liveness constaints in region inference context.
312+
pub fn number_of_liveness_constraints(&self) -> usize {
313+
self.liveness_constraints.len()
314+
}
315+
316+
/// Returns all the elements contained in a given region's value.
317+
crate fn elements_contained_in<'a>(
318+
&'a self,
319+
r: RegionVid,
320+
) -> impl Iterator<Item = RegionElement> + 'a {
321+
self.liveness_constraints.elements_contained_in(r)
322+
}
323+
307324
/// Given a universal region in scope on the MIR, returns the
308325
/// corresponding index.
309326
///
@@ -414,7 +431,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
414431
constraints
415432
});
416433

417-
// To propagate constriants, we walk the DAG induced by the
434+
// To propagate constraints, we walk the DAG induced by the
418435
// SCC. For each SCC, we visit its successors and compute
419436
// their values, then we union all those values to get our
420437
// own.

0 commit comments

Comments
 (0)