Skip to content

Commit

Permalink
Make causal tracking lazy
Browse files Browse the repository at this point in the history
  • Loading branch information
spastorino committed Jul 1, 2018
1 parent 24f91e8 commit 0957ede
Show file tree
Hide file tree
Showing 14 changed files with 225 additions and 319 deletions.
29 changes: 29 additions & 0 deletions src/librustc/mir/mod.rs
Expand Up @@ -1000,6 +1000,10 @@ impl<'tcx> Terminator<'tcx> {
self.kind.successors_mut()
}

pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
self.kind.unwind()
}

pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
self.kind.unwind_mut()
}
Expand Down Expand Up @@ -1195,6 +1199,31 @@ impl<'tcx> TerminatorKind<'tcx> {
}
}

pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
match *self {
TerminatorKind::Goto { .. }
| TerminatorKind::Resume
| TerminatorKind::Abort
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
| TerminatorKind::Yield { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::FalseEdges { .. } => None,
TerminatorKind::Call {
cleanup: ref unwind,
..
}
| TerminatorKind::Assert {
cleanup: ref unwind,
..
}
| TerminatorKind::DropAndReplace { ref unwind, .. }
| TerminatorKind::Drop { ref unwind, .. }
| TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind),
}
}

pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
match *self {
TerminatorKind::Goto { .. }
Expand Down
26 changes: 13 additions & 13 deletions src/librustc_mir/borrow_check/nll/constraint_generation.rs
Expand Up @@ -12,7 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
use borrow_check::location::LocationTable;
use borrow_check::nll::ToRegionVid;
use borrow_check::nll::facts::AllFacts;
use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
use borrow_check::nll::region_infer::RegionInferenceContext;
use borrow_check::nll::type_check::AtLocation;
use rustc::hir;
use rustc::infer::InferCtxt;
Expand All @@ -33,7 +33,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
location_table: &LocationTable,
mir: &Mir<'tcx>,
borrow_set: &BorrowSet<'tcx>,
liveness_set_from_typeck: &[(ty::Region<'tcx>, Location, Cause)],
liveness_set_from_typeck: &[(ty::Region<'tcx>, Location)],
) {
let mut cg = ConstraintGeneration {
borrow_set,
Expand Down Expand Up @@ -69,14 +69,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
/// We sometimes have `substs` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn visit_substs(&mut self, substs: &&'tcx Substs<'tcx>, location: Location) {
self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
self.add_regular_live_constraint(*substs, location);
self.super_substs(substs);
}

/// We sometimes have `region` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn visit_region(&mut self, region: &ty::Region<'tcx>, location: Location) {
self.add_regular_live_constraint(*region, location, Cause::LiveOther(location));
self.add_regular_live_constraint(*region, location);
self.super_region(region);
}

Expand All @@ -94,7 +94,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
);
}
TyContext::Location(location) => {
self.add_regular_live_constraint(*ty, location, Cause::LiveOther(location));
self.add_regular_live_constraint(*ty, location);
}
}

Expand All @@ -104,14 +104,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
/// We sometimes have `generator_substs` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) {
self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
self.add_regular_live_constraint(*substs, location);
self.super_generator_substs(substs);
}

/// We sometimes have `closure_substs` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, location: Location) {
self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
self.add_regular_live_constraint(*substs, location);
self.super_closure_substs(substs);
}

Expand Down Expand Up @@ -233,7 +233,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
/// that we also have to respect.
fn add_region_liveness_constraints_from_type_check(
&mut self,
liveness_set: &[(ty::Region<'tcx>, Location, Cause)],
liveness_set: &[(ty::Region<'tcx>, Location)],
) {
debug!(
"add_region_liveness_constraints_from_type_check(liveness_set={} items)",
Expand All @@ -247,16 +247,16 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
..
} = self;

for (region, location, cause) in liveness_set {
for (region, location) in liveness_set {
debug!("generate: {:#?} is live at {:#?}", region, location);
let region_vid = regioncx.to_region_vid(region);
regioncx.add_live_point(region_vid, *location, &cause);
regioncx.add_live_point(region_vid, *location);
}

if let Some(all_facts) = all_facts {
all_facts
.region_live_at
.extend(liveness_set.into_iter().flat_map(|(region, location, _)| {
.extend(liveness_set.into_iter().flat_map(|(region, location)| {
let r = regioncx.to_region_vid(region);
let p1 = location_table.start_index(*location);
let p2 = location_table.mid_index(*location);
Expand All @@ -269,7 +269,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
/// `location` -- i.e., it may be used later. This means that all
/// regions appearing in the type `live_ty` must be live at
/// `location`.
fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location, cause: Cause)
fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location)
where
T: TypeFoldable<'tcx>,
{
Expand All @@ -282,7 +282,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
.tcx
.for_each_free_region(&live_ty, |live_region| {
let vid = live_region.to_region_vid();
self.regioncx.add_live_point(vid, location, &cause);
self.regioncx.add_live_point(vid, location);
});
}

Expand Down
174 changes: 100 additions & 74 deletions src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
Expand Up @@ -8,74 +8,56 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use borrow_check::borrow_set::BorrowData;
use borrow_check::nll::region_infer::RegionInferenceContext;
use std::collections::VecDeque;
use std::rc::Rc;

use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
use borrow_check::nll::ToRegionVid;
use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
use rustc::mir::{Local, Location, Mir};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use util::liveness::{self, DefUse, LivenessMode};

crate fn regular_use<'gcx, 'tcx>(
mir: &'gcx Mir,
regioncx: &'tcx RegionInferenceContext,
borrow: &'tcx BorrowData,
crate fn find<'cx, 'gcx: 'tcx, 'tcx: 'cx>(
mir: &'cx Mir<'tcx>,
regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
region_vid: RegionVid,
start_point: Location,
local: Local,
) -> Option<Location> {
) -> Option<Cause> {
let mut uf = UseFinder {
mir,
regioncx,
borrow,
tcx,
region_vid,
start_point,
local,
liveness_mode: LivenessMode {
include_regular_use: true,
include_drops: false,
},
};

uf.find()
}

crate fn drop_use<'gcx, 'tcx>(
mir: &'gcx Mir,
regioncx: &'tcx RegionInferenceContext,
borrow: &'tcx BorrowData,
start_point: Location,
local: Local,
) -> Option<Location> {
let mut uf = UseFinder {
mir,
regioncx,
borrow,
start_point,
local,
liveness_mode: LivenessMode {
include_regular_use: false,
include_drops: true,
},
};

uf.find()
}

struct UseFinder<'gcx, 'tcx> {
mir: &'gcx Mir<'gcx>,
regioncx: &'tcx RegionInferenceContext<'tcx>,
borrow: &'tcx BorrowData<'tcx>,
struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
mir: &'cx Mir<'tcx>,
regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
region_vid: RegionVid,
start_point: Location,
local: Local,
liveness_mode: LivenessMode,
}

impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
fn find(&mut self) -> Option<Location> {
let mut stack = vec![];
impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
fn find(&mut self) -> Option<Cause> {
let mut queue = VecDeque::new();
let mut visited = FxHashSet();

stack.push(self.start_point);
while let Some(p) = stack.pop() {
if !self.regioncx.region_contains_point(self.borrow.region, p) {
queue.push_back(self.start_point);
while let Some(p) = queue.pop_front() {
if !self.regioncx.region_contains_point(self.region_vid, p) {
continue;
}

Expand All @@ -84,58 +66,102 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
}

let block_data = &self.mir[p.block];
let (defined, used) = self.def_use(p, block_data.visitable(p.statement_index));

if used {
return Some(p);
} else if !defined {
if p.statement_index < block_data.statements.len() {
stack.push(Location {
statement_index: p.statement_index + 1,
..p
});
} else {
stack.extend(block_data.terminator().successors().map(|&basic_block| {
Location {
statement_index: 0,
block: basic_block,
}
}));

match self.def_use(p, block_data.visitable(p.statement_index)) {
Some(DefUseResult::Def) => {}

Some(DefUseResult::UseLive { local }) => {
return Some(Cause::LiveVar(local, p));
}

Some(DefUseResult::UseDrop { local }) => {
return Some(Cause::DropVar(local, p));
}

None => {
if p.statement_index < block_data.statements.len() {
queue.push_back(Location {
statement_index: p.statement_index + 1,
..p
});
} else {
queue.extend(
block_data
.terminator()
.successors()
.filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind())
.map(|&bb| Location {
statement_index: 0,
block: bb,
}),
);
}
}
}
}

None
}

fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> (bool, bool) {
fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
let mut visitor = DefUseVisitor {
defined: false,
used: false,
local: self.local,
mir: self.mir,
tcx: self.tcx,
region_vid: self.region_vid,
liveness_mode: self.liveness_mode,
def_use_result: None,
};

thing.apply(location, &mut visitor);

(visitor.defined, visitor.used)
visitor.def_use_result
}
}

struct DefUseVisitor {
defined: bool,
used: bool,
local: Local,
struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
mir: &'cx Mir<'tcx>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
region_vid: RegionVid,
liveness_mode: LivenessMode,
def_use_result: Option<DefUseResult>,
}

enum DefUseResult {
Def,

UseLive { local: Local },

UseDrop { local: Local },
}

impl<'tcx> Visitor<'tcx> for DefUseVisitor {
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> {
fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
if local == self.local {
let local_ty = self.mir.local_decls[local].ty;

let mut found_it = false;
self.tcx.for_each_free_region(&local_ty, |r| {
if r.to_region_vid() == self.region_vid {
found_it = true;
}
});

if found_it {
match liveness::categorize(context, self.liveness_mode) {
Some(DefUse::Def) => self.defined = true,
Some(DefUse::Use) => self.used = true,
None => (),
Some(DefUse::Def) => {
self.def_use_result = Some(DefUseResult::Def);
}

Some(DefUse::Use) => {
self.def_use_result = if context.is_drop() {
Some(DefUseResult::UseDrop { local })
} else {
Some(DefUseResult::UseLive { local })
};
}

None => {
self.def_use_result = None;
}
}
}
}
Expand Down

0 comments on commit 0957ede

Please sign in to comment.