Skip to content

Commit 025e04e

Browse files
committed
Auto merge of #52190 - davidtwco:issue-52028, r=nikomatsakis
html5ever in the rustc-perf repository is memory-intensive Part of #52028. Rebased atop of #51987. r? @nikomatsakis
2 parents 2ddc0cb + 8b94d16 commit 025e04e

File tree

9 files changed

+174
-121
lines changed

9 files changed

+174
-121
lines changed

src/librustc_data_structures/bitvec.rs

+47-9
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,6 +293,14 @@ 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+
debug!(
297+
"add(row={:?}, column={:?}, current_len={})",
298+
row,
299+
column,
300+
self.vector.len()
301+
);
302+
self.vector
303+
.ensure_contains_elem(row, || SparseBitSet::new());
296304
self.vector[row].insert(column)
297305
}
298306

@@ -301,7 +309,7 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
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`,
@@ -315,16 +323,27 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
315323
let mut changed = false;
316324

317325
if read != write {
318-
let (bit_set_read, bit_set_write) = self.vector.pick2_mut(read, write);
326+
if self.vector.get(read).is_some() {
327+
self.vector
328+
.ensure_contains_elem(write, || SparseBitSet::new());
329+
let (bit_set_read, bit_set_write) = self.vector.pick2_mut(read, write);
319330

320-
for read_chunk in bit_set_read.chunks() {
321-
changed = changed | bit_set_write.insert_chunk(read_chunk).any();
331+
for read_chunk in bit_set_read.chunks() {
332+
changed = changed | bit_set_write.insert_chunk(read_chunk).any();
333+
}
322334
}
323335
}
324336

325337
changed
326338
}
327339

340+
/// Merge a row, `from`, into the `into` row.
341+
pub fn merge_into(&mut self, into: R, from: &SparseBitSet<C>) -> bool {
342+
self.vector
343+
.ensure_contains_elem(into, || SparseBitSet::new());
344+
self.vector[into].insert_from(from)
345+
}
346+
328347
/// True if `sub` is a subset of `sup`
329348
pub fn is_subset(&self, sub: R, sup: R) -> bool {
330349
sub == sup || {
@@ -336,10 +355,20 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
336355
}
337356
}
338357

358+
/// Number of elements in the matrix.
359+
pub fn len(&self) -> usize {
360+
self.vector.len()
361+
}
362+
339363
/// Iterates through all the columns set to true in a given row of
340364
/// the matrix.
341365
pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
342-
self.vector[row].iter()
366+
self.vector.get(row).into_iter().flat_map(|r| r.iter())
367+
}
368+
369+
/// Iterates through each row and the accompanying bit set.
370+
pub fn iter_enumerated<'a>(&'a self) -> impl Iterator<Item = (R, &'a SparseBitSet<C>)> + 'a {
371+
self.vector.iter_enumerated()
343372
}
344373
}
345374

@@ -445,6 +474,15 @@ impl<I: Idx> SparseBitSet<I> {
445474
}
446475
}
447476

477+
/// Insert into bit set from another bit set.
478+
pub fn insert_from(&mut self, from: &SparseBitSet<I>) -> bool {
479+
let mut changed = false;
480+
for read_chunk in from.chunks() {
481+
changed = changed | self.insert_chunk(read_chunk).any();
482+
}
483+
changed
484+
}
485+
448486
pub fn remove_chunk(&mut self, chunk: SparseChunk<I>) -> SparseChunk<I> {
449487
if chunk.bits == 0 {
450488
return chunk;

src/librustc_data_structures/indexed_vec.rs

+18
Original file line numberDiff line numberDiff line change
@@ -518,10 +518,28 @@ impl<I: Idx, T> IndexVec<I, T> {
518518
}
519519

520520
impl<I: Idx, T: Clone> IndexVec<I, T> {
521+
/// Grows the index vector so that it contains an entry for
522+
/// `elem`; if that is already true, then has no
523+
/// effect. Otherwise, inserts new values as needed by invoking
524+
/// `fill_value`.
525+
#[inline]
526+
pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
527+
let min_new_len = elem.index() + 1;
528+
if self.len() < min_new_len {
529+
self.raw.resize_with(min_new_len, fill_value);
530+
}
531+
}
532+
521533
#[inline]
522534
pub fn resize(&mut self, new_len: usize, value: T) {
523535
self.raw.resize(new_len, value)
524536
}
537+
538+
#[inline]
539+
pub fn resize_to_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
540+
let min_new_len = elem.index() + 1;
541+
self.raw.resize_with(min_new_len, fill_value);
542+
}
525543
}
526544

527545
impl<I: Idx, T: Ord> IndexVec<I, T> {

src/librustc_data_structures/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#![feature(optin_builtin_traits)]
3131
#![feature(macro_vis_matcher)]
3232
#![feature(allow_internal_unstable)]
33+
#![feature(vec_resize_with)]
3334

3435
#![cfg_attr(unix, feature(libc))]
3536
#![cfg_attr(test, feature(test))]

src/librustc_mir/borrow_check/nll/constraint_generation.rs

-40
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use rustc::mir::{Local, Statement, Terminator};
2121
use rustc::ty::fold::TypeFoldable;
2222
use rustc::ty::subst::Substs;
2323
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts};
24-
use std::iter;
2524

2625
pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
2726
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
@@ -30,7 +29,6 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
3029
location_table: &LocationTable,
3130
mir: &Mir<'tcx>,
3231
borrow_set: &BorrowSet<'tcx>,
33-
liveness_set_from_typeck: &[(ty::Region<'tcx>, Location)],
3432
) {
3533
let mut cg = ConstraintGeneration {
3634
borrow_set,
@@ -40,8 +38,6 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
4038
all_facts,
4139
};
4240

43-
cg.add_region_liveness_constraints_from_type_check(liveness_set_from_typeck);
44-
4541
for (bb, data) in mir.basic_blocks().iter_enumerated() {
4642
cg.visit_basic_block_data(bb, data);
4743
}
@@ -189,42 +185,6 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
189185
}
190186

191187
impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
192-
/// The MIR type checker generates region liveness constraints
193-
/// 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-
203-
let ConstraintGeneration {
204-
regioncx,
205-
location_table,
206-
all_facts,
207-
..
208-
} = self;
209-
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-
}
215-
216-
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-
}));
225-
}
226-
}
227-
228188
/// Some variable with type `live_ty` is "regular live" at
229189
/// `location` -- i.e., it may be used later. This means that all
230190
/// regions appearing in the type `live_ty` must be live at

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::values::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/mod.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ mod annotation;
3737
mod dump_mir;
3838
mod error_reporting;
3939
mod graphviz;
40-
mod values;
40+
pub mod values;
4141
use self::values::{RegionValueElements, RegionValues};
4242

4343
use super::ToRegionVid;
@@ -66,8 +66,8 @@ pub struct RegionInferenceContext<'tcx> {
6666
/// the SCC (see `constraint_sccs`) and for error reporting.
6767
constraint_graph: Rc<ConstraintGraph>,
6868

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

7373
/// The final inferred values of the region variables; we compute
@@ -207,15 +207,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
207207
pub(crate) fn new(
208208
var_infos: VarInfos,
209209
universal_regions: UniversalRegions<'tcx>,
210-
mir: &Mir<'tcx>,
210+
_mir: &Mir<'tcx>,
211211
outlives_constraints: ConstraintSet,
212212
type_tests: Vec<TypeTest<'tcx>>,
213+
liveness_constraints: RegionValues<RegionVid>,
214+
elements: &Rc<RegionValueElements>,
213215
) -> Self {
214216
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));
219217

220218
// Create a RegionDefinition for each inference variable.
221219
let definitions: IndexVec<_, _> = var_infos
@@ -227,15 +225,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
227225
let constraint_graph = Rc::new(constraints.graph(definitions.len()));
228226
let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph));
229227

230-
let scc_values = RegionValues::new(elements, constraint_sccs.num_sccs());
228+
let mut scc_values = RegionValues::new(elements);
229+
230+
for (region, location_set) in liveness_constraints.iter_enumerated() {
231+
let scc = constraint_sccs.scc(region);
232+
scc_values.merge_into(scc, location_set);
233+
}
231234

232235
let mut result = Self {
233236
definitions,
234237
elements: elements.clone(),
235-
liveness_constraints: RegionValues::new(elements, num_region_variables),
238+
liveness_constraints,
236239
constraints,
237-
constraint_sccs,
238240
constraint_graph,
241+
constraint_sccs,
239242
scc_values,
240243
type_tests,
241244
universal_regions,
@@ -414,7 +417,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
414417
constraints
415418
});
416419

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

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

+15-16
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use rustc::mir::{BasicBlock, Location, Mir};
1212
use rustc::ty::RegionVid;
13-
use rustc_data_structures::bitvec::SparseBitMatrix;
13+
use rustc_data_structures::bitvec::{SparseBitMatrix, SparseBitSet};
1414
use rustc_data_structures::indexed_vec::Idx;
1515
use rustc_data_structures::indexed_vec::IndexVec;
1616
use std::fmt::Debug;
@@ -55,11 +55,6 @@ impl RegionValueElements {
5555
}
5656
}
5757

58-
/// Total number of element indices that exist.
59-
crate fn num_elements(&self) -> usize {
60-
self.num_points + self.num_universal_regions
61-
}
62-
6358
/// Converts an element of a region value into a `RegionElementIndex`.
6459
crate fn index<T: ToElementIndex>(&self, elem: T) -> RegionElementIndex {
6560
elem.to_element_index(self)
@@ -188,18 +183,10 @@ impl<N: Idx> RegionValues<N> {
188183
/// Creates a new set of "region values" that tracks causal information.
189184
/// Each of the regions in num_region_variables will be initialized with an
190185
/// empty set of points and no causal information.
191-
crate fn new(elements: &Rc<RegionValueElements>, num_region_variables: usize) -> Self {
192-
assert!(
193-
elements.num_universal_regions <= num_region_variables,
194-
"universal regions are a subset of the region variables"
195-
);
196-
186+
crate fn new(elements: &Rc<RegionValueElements>) -> Self {
197187
Self {
198188
elements: elements.clone(),
199-
matrix: SparseBitMatrix::new(
200-
N::new(num_region_variables),
201-
RegionElementIndex::new(elements.num_elements()),
202-
),
189+
matrix: SparseBitMatrix::new(),
203190
}
204191
}
205192

@@ -227,6 +214,18 @@ impl<N: Idx> RegionValues<N> {
227214
self.matrix.contains(r, i)
228215
}
229216

217+
/// Iterates through each row and the accompanying bit set.
218+
pub fn iter_enumerated<'a>(
219+
&'a self
220+
) -> impl Iterator<Item = (N, &'a SparseBitSet<RegionElementIndex>)> + 'a {
221+
self.matrix.iter_enumerated()
222+
}
223+
224+
/// Merge a row, `from`, originating in another `RegionValues` into the `into` row.
225+
pub fn merge_into(&mut self, into: N, from: &SparseBitSet<RegionElementIndex>) -> bool {
226+
self.matrix.merge_into(into, from)
227+
}
228+
230229
/// True if `sup_region` contains all the CFG points that
231230
/// `sub_region` contains. Ignores universal regions.
232231
crate fn contains_points(&self, sup_region: N, sub_region: N) -> bool {

0 commit comments

Comments
 (0)