Skip to content

Commit e253d5b

Browse files
committed
Temp: Caching
1 parent afe8a41 commit e253d5b

File tree

1 file changed

+78
-47
lines changed

1 file changed

+78
-47
lines changed

src/librustc_mir/build/scope.rs

Lines changed: 78 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ pub struct Scopes<'tcx> {
102102

103103
/// Drops that need to be done on paths to the `GeneratorDrop` terminator.
104104
generator_drops: DropTree,
105-
106-
// TODO: implement caching
107-
// cached_unwind_drop: DropIdx,
108105
}
109106

110107
#[derive(Debug)]
@@ -125,6 +122,14 @@ struct Scope {
125122
drops: Vec<DropData>,
126123

127124
moved_locals: Vec<Local>,
125+
126+
/// The drop index that will drop everything in and below this scope on an
127+
/// unwind path.
128+
cached_unwind_block: Option<DropIdx>,
129+
130+
/// The drop index that will drop everything in and below this scope on a
131+
/// generator drop path.
132+
cached_generator_drop_block: Option<DropIdx>,
128133
}
129134

130135
#[derive(Clone, Copy, Debug)]
@@ -211,6 +216,11 @@ impl Scope {
211216
DropKind::Storage => false,
212217
})
213218
}
219+
220+
fn invalidate_cache(&mut self) {
221+
self.cached_unwind_block = None;
222+
self.cached_generator_drop_block = None;
223+
}
214224
}
215225

216226
/// A trait that determined how [DropTree::lower_to_mir] creates its blocks and
@@ -387,6 +397,8 @@ impl<'tcx> Scopes<'tcx> {
387397
region_scope_span: region_scope.1.span,
388398
drops: vec![],
389399
moved_locals: vec![],
400+
cached_unwind_block: None,
401+
cached_generator_drop_block: None,
390402
});
391403
}
392404

@@ -407,10 +419,6 @@ impl<'tcx> Scopes<'tcx> {
407419
})
408420
}
409421

410-
fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item=&mut Scope> + '_ {
411-
self.scopes.iter_mut().rev()
412-
}
413-
414422
/// Returns the topmost active scope, which is known to be alive until
415423
/// the next scope expression.
416424
fn topmost(&self) -> region::Scope {
@@ -611,10 +619,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
611619
} else {
612620
self.scopes.breakable_scopes[break_index].continue_drops.as_mut().unwrap()
613621
};
614-
615-
let mut drop_idx = DropIdx::from_u32(destination.is_none() as u32);
616-
for drop in scope_drops {
617-
drop_idx = drops.add_drop(*drop, drop_idx);
622+
let mut drop_idx = ROOT_NODE;
623+
for scope in &self.scopes.scopes[scope_index + 1..] {
624+
for drop in &scope.drops {
625+
drop_idx = drops.add_drop(*drop, drop_idx);
626+
}
618627
}
619628
drops.add_entry(block, drop_idx);
620629
// `build_drop_tree` doesn't have access to our source_info, so we
@@ -671,19 +680,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
671680
))
672681
}
673682

674-
/// Sets up a path that performs all required cleanup for dropping a generator.
675-
///
676-
/// This path terminates in GeneratorDrop. Returns the start of the path.
677-
/// None indicates there’s no cleanup to do at this point.
678-
crate fn generator_drop_cleanup(&mut self, yield_block: BasicBlock) {
679-
let drops = self.scopes.scopes.iter().flat_map(|scope| &scope.drops);
680-
let mut next_drop = ROOT_NODE;
681-
for drop in drops {
682-
next_drop = self.scopes.generator_drops.add_drop(*drop, next_drop);
683-
}
684-
self.scopes.generator_drops.add_entry(yield_block, next_drop);
685-
}
686-
687683
/// Creates a new source scope, nested in the current one.
688684
crate fn new_source_scope(&mut self,
689685
span: Span,
@@ -778,8 +774,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
778774
local: Local,
779775
drop_kind: DropKind,
780776
) {
781-
// TODO: add back in caching.
782-
let _needs_drop = match drop_kind {
777+
let needs_drop = match drop_kind {
783778
DropKind::Value => {
784779
if !self.hir.needs_drop(self.local_decls[local].ty) { return }
785780
true
@@ -796,21 +791,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
796791
}
797792
};
798793

799-
let scope = self.scopes.iter_mut()
800-
.find(|scope| scope.region_scope == region_scope)
801-
.unwrap_or_else(|| {
802-
span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, local);
803-
});
794+
let invalidate_caches = needs_drop || self.is_generator;
795+
for scope in self.scopes.scopes.iter_mut().rev() {
796+
if invalidate_caches {
797+
scope.invalidate_cache();
798+
}
804799

805-
let region_scope_span = region_scope.span(self.hir.tcx(), &self.hir.region_scope_tree);
806-
// Attribute scope exit drops to scope's closing brace.
807-
let scope_end = self.hir.tcx().sess.source_map().end_point(region_scope_span);
800+
if scope.region_scope == region_scope {
801+
let region_scope_span = region_scope.span(self.hir.tcx(), &self.hir.region_scope_tree);
802+
// Attribute scope exit drops to scope's closing brace.
803+
let scope_end = self.hir.tcx().sess.source_map().end_point(region_scope_span);
808804

809-
scope.drops.push(DropData {
810-
source_info: SourceInfo { span: scope_end, scope: scope.source_scope },
811-
local,
812-
kind: drop_kind,
813-
});
805+
scope.drops.push(DropData {
806+
source_info: SourceInfo { span: scope_end, scope: scope.source_scope },
807+
local,
808+
kind: drop_kind,
809+
});
810+
811+
return;
812+
}
813+
}
814+
815+
span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, local);
814816
}
815817

816818
/// Indicates that the "local operand" stored in `local` is
@@ -857,7 +859,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
857859
}
858860

859861
Some(local_scope) => {
860-
self.scopes.iter_mut().find(|scope| scope.region_scope == local_scope)
862+
self.scopes.scopes.iter_mut().rfind(|scope| scope.region_scope == local_scope)
861863
.unwrap_or_else(|| bug!("scope {:?} not found in scope list!", local_scope))
862864
}
863865
};
@@ -914,6 +916,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
914916
// Manually drop the condition on both branches.
915917
let top_scope = self.scopes.scopes.last_mut().unwrap();
916918
let top_drop_data = top_scope.drops.pop().unwrap();
919+
if self.is_generator {
920+
top_scope.invalidate_cache();
921+
}
917922

918923
match top_drop_data.kind {
919924
DropKind::Value { .. } => {
@@ -950,14 +955,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
950955

951956
fn diverge_cleanup(&mut self) -> DropIdx {
952957
let is_generator = self.is_generator;
953-
let drops = self.scopes.scopes.iter()
954-
.flat_map(|scope| &scope.drops)
955-
.filter(|drop| is_generator || drop.kind == DropKind::Value);
956-
let mut next_drop = ROOT_NODE;
957-
for drop in drops {
958-
next_drop = self.scopes.unwind_drops.add_drop(*drop, next_drop);
958+
let (uncached_scope, mut cached_drop) = self.scopes.scopes.iter().enumerate().rev()
959+
.find_map(|(scope_idx, scope)| {
960+
scope.cached_unwind_block.map(|cached_block| (scope_idx + 1, cached_block))
961+
})
962+
.unwrap_or((0, ROOT_NODE));
963+
for scope in &mut self.scopes.scopes[uncached_scope..] {
964+
for drop in &scope.drops {
965+
if is_generator || drop.kind == DropKind::Value {
966+
cached_drop = self.scopes.unwind_drops.add_drop(*drop, cached_drop);
967+
}
968+
}
969+
scope.cached_unwind_block = Some(cached_drop);
959970
}
960-
next_drop
971+
cached_drop
961972
}
962973

963974
/// Prepares to create a path that performs all required cleanup for
@@ -970,6 +981,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
970981
self.scopes.unwind_drops.add_entry(start, next_drop);
971982
}
972983

984+
/// Sets up a path that performs all required cleanup for dropping a generator.
985+
///
986+
/// This path terminates in GeneratorDrop. Returns the start of the path.
987+
/// None indicates there’s no cleanup to do at this point.
988+
crate fn generator_drop_cleanup(&mut self, yield_block: BasicBlock) {
989+
let (uncached_scope, mut cached_drop) = self.scopes.scopes.iter().enumerate().rev()
990+
.find_map(|(scope_idx, scope)| {
991+
scope.cached_generator_drop_block.map(|cached_block| (scope_idx + 1, cached_block))
992+
})
993+
.unwrap_or((0, ROOT_NODE));
994+
for scope in &mut self.scopes.scopes[uncached_scope..] {
995+
for drop in &scope.drops {
996+
cached_drop = self.scopes.generator_drops.add_drop(*drop, cached_drop);
997+
}
998+
scope.cached_generator_drop_block = Some(cached_drop);
999+
}
1000+
self.scopes.generator_drops.add_entry(yield_block, cached_drop);
1001+
}
1002+
9731003
/// Utility function for *non*-scope code to build their own drops
9741004
crate fn build_drop_and_replace(&mut self,
9751005
block: BasicBlock,
@@ -1027,6 +1057,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10271057
assert_eq!(top_scope.region_scope, region_scope);
10281058

10291059
top_scope.drops.clear();
1060+
top_scope.invalidate_cache();
10301061
}
10311062
}
10321063

0 commit comments

Comments
 (0)