Skip to content

Commit ad73468

Browse files
committed
Move predecessors cache invalidation back to basic_blocks_mut, add a couple more ensure_predecessors to prevent panics
1 parent 8e8c97e commit ad73468

File tree

18 files changed

+102
-125
lines changed

18 files changed

+102
-125
lines changed

src/librustc/mir/mod.rs

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -203,23 +203,9 @@ impl<'tcx> Body<'tcx> {
203203

204204
#[inline]
205205
pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
206-
&mut self.basic_blocks
207-
}
208-
209-
pub fn basic_block_terminator_opt_mut(
210-
&mut self, bb: BasicBlock
211-
) -> &mut Option<Terminator<'tcx>> {
212-
// FIXME we should look into improving the cache invalidation
213-
debug!("Invalidating predecessors cache through opt terminator for block at : {:?}", self.span.data());
214-
self.predecessors_cache = None;
215-
&mut self.basic_blocks[bb].terminator
216-
}
217-
218-
pub fn basic_block_terminator_mut(&mut self, bb: BasicBlock) -> &mut Terminator<'tcx> {
219-
// FIXME we should look into improving the cache invalidation
220-
debug!("Invalidating predecessors cache through terminator for block at : {:?}", self.span.data());
206+
debug!("Clearing predecessors cache at: {:?}", self.span.data());
221207
self.predecessors_cache = None;
222-
self.basic_blocks[bb].terminator_mut()
208+
&mut self.basic_blocks
223209
}
224210

225211
#[inline]
@@ -1370,10 +1356,6 @@ impl<'tcx> BasicBlockData<'tcx> {
13701356
BasicBlockData { statements: vec![], terminator, is_cleanup: false }
13711357
}
13721358

1373-
pub fn terminator_opt(&self) -> &Option<Terminator<'tcx>> {
1374-
&self.terminator
1375-
}
1376-
13771359
/// Accessor for terminator.
13781360
///
13791361
/// Terminator may not be None after construction of the basic block is complete. This accessor
@@ -1382,17 +1364,10 @@ impl<'tcx> BasicBlockData<'tcx> {
13821364
self.terminator.as_ref().expect("invalid terminator state")
13831365
}
13841366

1385-
// This cannot be public since changing the terminator will break the predecessors cache in Body
1386-
// To do so outside of this module, use Body::basic_block_terminator_mut(BasicBlock)
1387-
fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
1367+
pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
13881368
self.terminator.as_mut().expect("invalid terminator state")
13891369
}
13901370

1391-
// This can be public since changing the kind will not break the predecessors cache in Body
1392-
pub fn terminator_kind_mut(&mut self) -> &mut TerminatorKind<'tcx> {
1393-
&mut self.terminator_mut().kind
1394-
}
1395-
13961371
pub fn retain_statements<F>(&mut self, mut f: F)
13971372
where
13981373
F: FnMut(&mut Statement<'_>) -> bool,

src/librustc/mir/traversal.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
5555

5656
let data = &self.body[idx];
5757

58-
if let Some(ref term) = data.terminator_opt() {
58+
if let Some(ref term) = data.terminator {
5959
self.worklist.extend(term.successors());
6060
}
6161

@@ -117,7 +117,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
117117

118118
let data = &po.body[root];
119119

120-
if let Some(ref term) = data.terminator_opt() {
120+
if let Some(ref term) = data.terminator {
121121
po.visited.insert(root);
122122
po.visit_stack.push((root, term.successors()));
123123
po.traverse_successor();
@@ -186,7 +186,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
186186
};
187187

188188
if self.visited.insert(bb) {
189-
if let Some(term) = &self.body[bb].terminator_opt() {
189+
if let Some(term) = &self.body[bb].terminator {
190190
self.visit_stack.push((bb, term.successors()));
191191
}
192192
}

src/librustc/mir/visit.rs

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -789,31 +789,18 @@ macro_rules! make_mir_visitor {
789789
}
790790

791791
// Convenience methods
792-
make_mir_visitor!{@make_visit_location, $($mutability)?}
793-
}
794-
};
795-
(@make_visit_location, mut) => {
796-
fn visit_location(&mut self, body: &mut Body<'tcx>, location: Location) {
797-
if body[location.block].statements.len() == location.statement_index {
798-
if let Some(ref mut terminator) = body.basic_block_terminator_opt_mut(location.block) {
799-
self.visit_terminator(terminator, location)
800-
}
801-
} else {
802-
let statement = &mut body[location.block].statements[location.statement_index];
803-
self.visit_statement(statement, location)
804-
}
805-
}
806-
};
807-
(@make_visit_location, ) => {
808-
fn visit_location(&mut self, body: &Body<'tcx>, location: Location) {
809-
let basic_block = &body[location.block];
810-
if basic_block.statements.len() == location.statement_index {
811-
if let Some(ref terminator) = basic_block.terminator_opt() {
812-
self.visit_terminator(terminator, location)
792+
793+
fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) {
794+
let basic_block = & $($mutability)? body[location.block];
795+
if basic_block.statements.len() == location.statement_index {
796+
if let Some(ref $($mutability)? terminator) = basic_block.terminator {
797+
self.visit_terminator(terminator, location)
798+
}
799+
} else {
800+
let statement = & $($mutability)?
801+
basic_block.statements[location.statement_index];
802+
self.visit_statement(statement, location)
813803
}
814-
} else {
815-
let statement = &basic_block.statements[location.statement_index];
816-
self.visit_statement(statement, location)
817804
}
818805
}
819806
}

src/librustc_codegen_ssa/mir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
265265

266266
let funclet;
267267
let ret_llbb;
268-
match mir[bb].terminator_opt().as_ref().map(|t| &t.kind) {
268+
match mir[bb].terminator.as_ref().map(|t| &t.kind) {
269269
// This is a basic block that we're aborting the program for,
270270
// notably in an `extern` function. These basic blocks are inserted
271271
// so that we assert that `extern` functions do indeed not panic,

src/librustc_mir/borrow_check/error_reporting.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
497497
..
498498
},
499499
..
500-
}) = bbd.terminator_opt() {
500+
}) = bbd.terminator {
501501
if let Some(source)
502502
= BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
503503
{

src/librustc_mir/borrow_check/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ fn do_mir_borrowck<'a, 'tcx>(
166166
let mut promoted: IndexVec<Promoted, Body<'tcx>> = input_promoted.clone();
167167
let free_regions =
168168
nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted);
169+
170+
// Region replacement above very likely invalidated the predecessors cache. It's used later on
171+
// when retrieving the dominators from the body, so we need to ensure it exists before locking
172+
// the body for changes.
173+
body.ensure_predecessors();
169174
let body = &body; // no further changes
170175
let location_table = &LocationTable::new(body);
171176

src/librustc_mir/build/cfg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ impl<'tcx> CFG<'tcx> {
6464
source_info: SourceInfo,
6565
kind: TerminatorKind<'tcx>) {
6666
debug!("terminating block {:?} <- {:?}", block, kind);
67-
debug_assert!(self.block_data(block).terminator_opt().is_none(),
67+
debug_assert!(self.block_data(block).terminator.is_none(),
6868
"terminate: block {:?}={:?} already has a terminator set",
6969
block,
7070
self.block_data(block));

src/librustc_mir/build/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
731731

732732
fn finish(self) -> Body<'tcx> {
733733
for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
734-
if block.terminator_opt().is_none() {
734+
if block.terminator.is_none() {
735735
span_bug!(self.fn_span, "no terminator on block {:?}", index);
736736
}
737737
}

src/librustc_mir/lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn check_fn_for_unconditional_recursion(
7979

8080
let block = &basic_blocks[bb];
8181

82-
if let Some(ref terminator) = block.terminator_opt() {
82+
if let Some(ref terminator) = block.terminator {
8383
match terminator.kind {
8484
TerminatorKind::Call { ref func, .. } => {
8585
let func_ty = func.ty(body, tcx);

src/librustc_mir/shim.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
123123
&add_call_guards::CriticalCallEdges,
124124
]);
125125

126+
// The `ensure_predecessors_cache::EnsurePredecessorsCache` MirPass wasn't used in the
127+
// `run_passes` above because the above pass is not always guaranteed to run. There can be
128+
// instances where, e.g. a `MirPhase::Validated` pass has already been run on a `Body` by the
129+
// time it arrived at this line, and so the above `run_passes` call will NOT run any of the
130+
// passes (They do not run if a same or later pass has already been executed on a `Body`).
131+
// Adding the ensure pass during the `run_passes` for `MirPhase::Validated` would not
132+
// help because the predecessors cache would be invalidated between that pass and this call.
133+
// Having the single ensure outside of the `run_passes` list here guarantees that anyone
134+
// using this `Body` could call `Body::unwrap_predecessors()` without worrying about a panic.
126135
result.ensure_predecessors();
127136

128137
debug!("make_shim({:?}) = {:?}", instance, result);

0 commit comments

Comments
 (0)