Skip to content

Commit fdc0011

Browse files
committed
Auto merge of #64736 - Nashenas88:mir_predecessors_cache_cleanup, r=oli-obk
Remove interior mutability in mir predecessors cache
2 parents 2da942f + 3eaad56 commit fdc0011

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+942
-590
lines changed

src/librustc/arena.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ macro_rules! arena_types {
2323
[] generics: rustc::ty::Generics,
2424
[] trait_def: rustc::ty::TraitDef,
2525
[] adt_def: rustc::ty::AdtDef,
26-
[] steal_mir: rustc::ty::steal::Steal<rustc::mir::Body<$tcx>>,
27-
[] mir: rustc::mir::Body<$tcx>,
26+
[] steal_mir: rustc::ty::steal::Steal<rustc::mir::BodyCache<$tcx>>,
27+
[] mir: rustc::mir::BodyCache<$tcx>,
2828
[] steal_promoted: rustc::ty::steal::Steal<
2929
rustc_index::vec::IndexVec<
3030
rustc::mir::Promoted,
31-
rustc::mir::Body<$tcx>
31+
rustc::mir::BodyCache<$tcx>
3232
>
3333
>,
3434
[] promoted: rustc_index::vec::IndexVec<
3535
rustc::mir::Promoted,
36-
rustc::mir::Body<$tcx>
36+
rustc::mir::BodyCache<$tcx>
3737
>,
3838
[] tables: rustc::ty::TypeckTables<$tcx>,
3939
[] const_allocs: rustc::mir::interpret::Allocation,

src/librustc/mir/cache.rs

+251-23
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
use rustc_index::vec::IndexVec;
2-
use rustc_data_structures::sync::{RwLock, MappedReadGuard, ReadGuard};
32
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
43
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
54
use crate::ich::StableHashingContext;
6-
use crate::mir::{Body, BasicBlock};
5+
use crate::mir::{BasicBlock, BasicBlockData, Body, LocalDecls, Location, Successors};
6+
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
7+
use rustc_data_structures::graph::dominators::{dominators, Dominators};
8+
use std::iter;
9+
use std::ops::{Deref, DerefMut, Index, IndexMut};
10+
use std::vec::IntoIter;
711

812
#[derive(Clone, Debug)]
913
pub struct Cache {
10-
predecessors: RwLock<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
14+
predecessors: Option<IndexVec<BasicBlock, Vec<BasicBlock>>>,
1115
}
1216

13-
1417
impl rustc_serialize::Encodable for Cache {
1518
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
1619
Encodable::encode(&(), s)
@@ -31,39 +34,264 @@ impl<'a> HashStable<StableHashingContext<'a>> for Cache {
3134

3235
impl Cache {
3336
pub fn new() -> Self {
34-
Cache {
35-
predecessors: RwLock::new(None)
37+
Self {
38+
predecessors: None,
3639
}
3740
}
3841

39-
pub fn invalidate(&self) {
42+
pub fn invalidate_predecessors(&mut self) {
4043
// FIXME: consider being more fine-grained
41-
*self.predecessors.borrow_mut() = None;
44+
self.predecessors = None;
4245
}
4346

44-
pub fn predecessors(
45-
&self,
46-
body: &Body<'_>
47-
) -> MappedReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
48-
if self.predecessors.borrow().is_none() {
49-
*self.predecessors.borrow_mut() = Some(calculate_predecessors(body));
47+
pub fn ensure_predecessors(&mut self, body: &Body<'_>) {
48+
if self.predecessors.is_none() {
49+
let mut result = IndexVec::from_elem(vec![], body.basic_blocks());
50+
for (bb, data) in body.basic_blocks().iter_enumerated() {
51+
if let Some(ref term) = data.terminator {
52+
for &tgt in term.successors() {
53+
result[tgt].push(bb);
54+
}
55+
}
56+
}
57+
58+
self.predecessors = Some(result)
5059
}
60+
}
61+
62+
/// This will recompute the predecessors cache if it is not available
63+
fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
64+
self.ensure_predecessors(body);
65+
self.predecessors.as_ref().unwrap()
66+
}
67+
68+
fn unwrap_predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] {
69+
&self.predecessors.as_ref().unwrap()[bb]
70+
}
5171

52-
ReadGuard::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
72+
fn unwrap_predecessor_locations<'a>(
73+
&'a self,
74+
loc: Location,
75+
body: &'a Body<'a>
76+
) -> impl Iterator<Item = Location> + 'a {
77+
let if_zero_locations = if loc.statement_index == 0 {
78+
let predecessor_blocks = self.unwrap_predecessors_for(loc.block);
79+
let num_predecessor_blocks = predecessor_blocks.len();
80+
Some(
81+
(0..num_predecessor_blocks)
82+
.map(move |i| predecessor_blocks[i])
83+
.map(move |bb| body.terminator_loc(bb)),
84+
)
85+
} else {
86+
None
87+
};
88+
89+
let if_not_zero_locations = if loc.statement_index == 0 {
90+
None
91+
} else {
92+
Some(Location { block: loc.block, statement_index: loc.statement_index - 1 })
93+
};
94+
95+
if_zero_locations.into_iter().flatten().chain(if_not_zero_locations)
96+
}
97+
98+
pub fn basic_blocks_mut<'a, 'tcx>(
99+
&mut self,
100+
body: &'a mut Body<'tcx>
101+
) -> &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
102+
debug!("bbm: Clearing predecessors cache for body at: {:?}", body.span.data());
103+
self.invalidate_predecessors();
104+
&mut body.basic_blocks
105+
}
106+
107+
pub fn basic_blocks_and_local_decls_mut<'a, 'tcx>(
108+
&mut self,
109+
body: &'a mut Body<'tcx>
110+
) -> (&'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &'a mut LocalDecls<'tcx>) {
111+
debug!("bbaldm: Clearing predecessors cache for body at: {:?}", body.span.data());
112+
self.invalidate_predecessors();
113+
(&mut body.basic_blocks, &mut body.local_decls)
53114
}
54115
}
55116

56-
fn calculate_predecessors(body: &Body<'_>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
57-
let mut result = IndexVec::from_elem(vec![], body.basic_blocks());
58-
for (bb, data) in body.basic_blocks().iter_enumerated() {
59-
if let Some(ref term) = data.terminator {
60-
for &tgt in term.successors() {
61-
result[tgt].push(bb);
62-
}
117+
#[derive(Clone, Debug, HashStable, RustcEncodable, RustcDecodable, TypeFoldable)]
118+
pub struct BodyCache<'tcx> {
119+
cache: Cache,
120+
body: Body<'tcx>,
121+
}
122+
123+
impl BodyCache<'tcx> {
124+
pub fn new(body: Body<'tcx>) -> Self {
125+
Self {
126+
cache: Cache::new(),
127+
body,
128+
}
129+
}
130+
}
131+
132+
#[macro_export]
133+
macro_rules! read_only {
134+
($body:expr) => {
135+
{
136+
$body.ensure_predecessors();
137+
$body.unwrap_read_only()
138+
}
139+
};
140+
}
141+
142+
impl BodyCache<'tcx> {
143+
pub fn ensure_predecessors(&mut self) {
144+
self.cache.ensure_predecessors(&self.body);
145+
}
146+
147+
pub fn predecessors(&mut self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
148+
self.cache.predecessors(&self.body)
149+
}
150+
151+
pub fn unwrap_read_only(&self) -> ReadOnlyBodyCache<'_, 'tcx> {
152+
ReadOnlyBodyCache::new(&self.cache, &self.body)
153+
}
154+
155+
pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
156+
self.cache.basic_blocks_mut(&mut self.body)
157+
}
158+
159+
pub fn basic_blocks_and_local_decls_mut(
160+
&mut self
161+
) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
162+
self.cache.basic_blocks_and_local_decls_mut(&mut self.body)
163+
}
164+
}
165+
166+
impl<'tcx> Index<BasicBlock> for BodyCache<'tcx> {
167+
type Output = BasicBlockData<'tcx>;
168+
169+
fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
170+
&self.body[index]
171+
}
172+
}
173+
174+
impl<'tcx> IndexMut<BasicBlock> for BodyCache<'tcx> {
175+
fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output {
176+
&mut self.basic_blocks_mut()[index]
177+
}
178+
}
179+
180+
impl<'tcx> Deref for BodyCache<'tcx> {
181+
type Target = Body<'tcx>;
182+
183+
fn deref(&self) -> &Self::Target {
184+
&self.body
185+
}
186+
}
187+
188+
impl<'tcx> DerefMut for BodyCache<'tcx> {
189+
fn deref_mut(&mut self) -> &mut Self::Target {
190+
&mut self.body
191+
}
192+
}
193+
194+
#[derive(Copy, Clone, Debug)]
195+
pub struct ReadOnlyBodyCache<'a, 'tcx> {
196+
cache: &'a Cache,
197+
body: &'a Body<'tcx>,
198+
}
199+
200+
impl ReadOnlyBodyCache<'a, 'tcx> {
201+
fn new(cache: &'a Cache, body: &'a Body<'tcx>) -> Self {
202+
assert!(
203+
cache.predecessors.is_some(),
204+
"Cannot construct ReadOnlyBodyCache without computed predecessors");
205+
Self {
206+
cache,
207+
body,
63208
}
64209
}
65210

66-
result
211+
pub fn predecessors(&self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
212+
self.cache.predecessors.as_ref().unwrap()
213+
}
214+
215+
pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] {
216+
self.cache.unwrap_predecessors_for(bb)
217+
}
218+
219+
pub fn predecessor_locations(&self, loc: Location) -> impl Iterator<Item = Location> + '_ {
220+
self.cache.unwrap_predecessor_locations(loc, self.body)
221+
}
222+
223+
pub fn body(&self) -> &'a Body<'tcx> {
224+
self.body
225+
}
226+
227+
pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
228+
&self.body.basic_blocks
229+
}
230+
231+
pub fn dominators(&self) -> Dominators<BasicBlock> {
232+
dominators(self)
233+
}
234+
}
235+
236+
impl graph::DirectedGraph for ReadOnlyBodyCache<'a, 'tcx> {
237+
type Node = BasicBlock;
238+
}
239+
240+
impl graph::GraphPredecessors<'graph> for ReadOnlyBodyCache<'a, 'tcx> {
241+
type Item = BasicBlock;
242+
type Iter = IntoIter<BasicBlock>;
243+
}
244+
245+
impl graph::WithPredecessors for ReadOnlyBodyCache<'a, 'tcx> {
246+
fn predecessors(
247+
&self,
248+
node: Self::Node,
249+
) -> <Self as GraphPredecessors<'_>>::Iter {
250+
self.cache.unwrap_predecessors_for(node).to_vec().into_iter()
251+
}
252+
}
253+
254+
impl graph::WithNumNodes for ReadOnlyBodyCache<'a, 'tcx> {
255+
fn num_nodes(&self) -> usize {
256+
self.body.num_nodes()
257+
}
258+
}
259+
260+
impl graph::WithStartNode for ReadOnlyBodyCache<'a, 'tcx> {
261+
fn start_node(&self) -> Self::Node {
262+
self.body.start_node()
263+
}
264+
}
265+
266+
impl graph::WithSuccessors for ReadOnlyBodyCache<'a, 'tcx> {
267+
fn successors(
268+
&self,
269+
node: Self::Node,
270+
) -> <Self as GraphSuccessors<'_>>::Iter {
271+
self.body.successors(node)
272+
}
273+
}
274+
275+
impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for ReadOnlyBodyCache<'a, 'tcx> {
276+
type Item = BasicBlock;
277+
type Iter = iter::Cloned<Successors<'b>>;
278+
}
279+
280+
281+
impl Deref for ReadOnlyBodyCache<'a, 'tcx> {
282+
type Target = Body<'tcx>;
283+
284+
fn deref(&self) -> &Self::Target {
285+
self.body
286+
}
287+
}
288+
289+
impl Index<BasicBlock> for ReadOnlyBodyCache<'a, 'tcx> {
290+
type Output = BasicBlockData<'tcx>;
291+
292+
fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
293+
&self.body[index]
294+
}
67295
}
68296

69297
CloneTypeFoldableAndLiftImpls! {

0 commit comments

Comments
 (0)