nll: remove NllLivenessMap from LocalUseMap
Extend `LocalUseMap`'s `IndexVec`s that track def/use/drop data to store the original `Local` indexes and not the compacted `LiveVar` ones (favoring speed and code simplicity over space). Remove the `NllLivenessMap` embedded inside it since it's no longer needed to perform the `LiveVar`/`Local` conversion.
This commit is contained in:
parent
200bc02a5e
commit
4ae4e0501b
2 changed files with 52 additions and 33 deletions
|
|
@ -1,6 +1,5 @@
|
|||
use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
|
||||
use crate::borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
|
||||
use crate::util::liveness::{categorize, DefUse, LiveVariableMap};
|
||||
use crate::util::liveness::{categorize, DefUse};
|
||||
use rustc::mir::visit::{PlaceContext, Visitor};
|
||||
use rustc::mir::{Local, Location, Mir};
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
|
|
@ -9,26 +8,33 @@ use rustc_data_structures::vec_linked_list as vll;
|
|||
/// A map that cross references each local with the locations where it
|
||||
/// is defined (assigned), used, or dropped. Used during liveness
|
||||
/// computation.
|
||||
crate struct LocalUseMap<'me> {
|
||||
liveness_map: &'me NllLivenessMap,
|
||||
|
||||
///
|
||||
/// We keep track only of `Local`s we'll do the liveness analysis later,
|
||||
/// this means that our internal `IndexVec`s will only be sparsely populated.
|
||||
/// In the time-memory trade-off between keeping compact vectors with new
|
||||
/// indexes (and needing to continuously map the `Local` index to its compact
|
||||
/// counterpart) and having `IndexVec`s that we only use a fraction of, time
|
||||
/// (and code simplicity) was favored. The rationale is that we only keep
|
||||
/// a small number of `IndexVec`s throughout the entire analysis while, in
|
||||
/// contrast, we're accessing each `Local` *many* times.
|
||||
crate struct LocalUseMap {
|
||||
/// Head of a linked list of **definitions** of each variable --
|
||||
/// definition in this context means assignment, e.g., `x` is
|
||||
/// defined in `x = y` but not `y`; that first def is the head of
|
||||
/// a linked list that lets you enumerate all places the variable
|
||||
/// is assigned.
|
||||
first_def_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
|
||||
first_def_at: IndexVec<Local, Option<AppearanceIndex>>,
|
||||
|
||||
/// Head of a linked list of **uses** of each variable -- use in
|
||||
/// this context means that the existing value of the variable is
|
||||
/// read or modified. e.g., `y` is used in `x = y` but not `x`.
|
||||
/// Note that `DROP(x)` terminators are excluded from this list.
|
||||
first_use_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
|
||||
first_use_at: IndexVec<Local, Option<AppearanceIndex>>,
|
||||
|
||||
/// Head of a linked list of **drops** of each variable -- these
|
||||
/// are a special category of uses corresponding to the drop that
|
||||
/// we add for each local variable.
|
||||
first_drop_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
|
||||
first_drop_at: IndexVec<Local, Option<AppearanceIndex>>,
|
||||
|
||||
appearances: IndexVec<AppearanceIndex, Appearance>,
|
||||
}
|
||||
|
|
@ -50,55 +56,68 @@ impl vll::LinkElem for Appearance {
|
|||
}
|
||||
}
|
||||
|
||||
impl LocalUseMap<'me> {
|
||||
impl LocalUseMap {
|
||||
crate fn build(
|
||||
liveness_map: &'me NllLivenessMap,
|
||||
live_locals: &Vec<Local>,
|
||||
elements: &RegionValueElements,
|
||||
mir: &Mir<'_>,
|
||||
) -> Self {
|
||||
let nones = IndexVec::from_elem_n(None, liveness_map.num_variables());
|
||||
let nones = IndexVec::from_elem_n(None, mir.local_decls.len());
|
||||
let mut local_use_map = LocalUseMap {
|
||||
liveness_map,
|
||||
first_def_at: nones.clone(),
|
||||
first_use_at: nones.clone(),
|
||||
first_drop_at: nones,
|
||||
appearances: IndexVec::new(),
|
||||
};
|
||||
|
||||
let mut locals_with_use_data: IndexVec<Local, bool> =
|
||||
IndexVec::from_elem_n(false, mir.local_decls.len());
|
||||
live_locals
|
||||
.iter()
|
||||
.for_each(|&local| locals_with_use_data[local] = true);
|
||||
|
||||
LocalUseMapBuild {
|
||||
local_use_map: &mut local_use_map,
|
||||
elements,
|
||||
}.visit_mir(mir);
|
||||
locals_with_use_data,
|
||||
}
|
||||
.visit_mir(mir);
|
||||
|
||||
local_use_map
|
||||
}
|
||||
|
||||
crate fn defs(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
|
||||
let live_var = self.liveness_map.from_local(local).unwrap();
|
||||
vll::iter(self.first_def_at[live_var], &self.appearances)
|
||||
vll::iter(self.first_def_at[local], &self.appearances)
|
||||
.map(move |aa| self.appearances[aa].point_index)
|
||||
}
|
||||
|
||||
crate fn uses(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
|
||||
let live_var = self.liveness_map.from_local(local).unwrap();
|
||||
vll::iter(self.first_use_at[live_var], &self.appearances)
|
||||
vll::iter(self.first_use_at[local], &self.appearances)
|
||||
.map(move |aa| self.appearances[aa].point_index)
|
||||
}
|
||||
|
||||
crate fn drops(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
|
||||
let live_var = self.liveness_map.from_local(local).unwrap();
|
||||
vll::iter(self.first_drop_at[live_var], &self.appearances)
|
||||
vll::iter(self.first_drop_at[local], &self.appearances)
|
||||
.map(move |aa| self.appearances[aa].point_index)
|
||||
}
|
||||
}
|
||||
|
||||
struct LocalUseMapBuild<'me, 'map: 'me> {
|
||||
local_use_map: &'me mut LocalUseMap<'map>,
|
||||
struct LocalUseMapBuild<'me> {
|
||||
local_use_map: &'me mut LocalUseMap,
|
||||
elements: &'me RegionValueElements,
|
||||
|
||||
// Vector used in `visit_local` to signal which `Local`s do we need
|
||||
// def/use/drop information on, constructed from `live_locals` (that
|
||||
// contains the variables we'll do the liveness analysis for).
|
||||
// This vector serves optimization purposes only: we could have
|
||||
// obtained the same information from `live_locals` but we want to
|
||||
// avoid repeatedly calling `Vec::contains()` (see `LocalUseMap` for
|
||||
// the rationale on the time-memory trade-off we're favoring here).
|
||||
locals_with_use_data: IndexVec<Local, bool>,
|
||||
}
|
||||
|
||||
impl LocalUseMapBuild<'_, '_> {
|
||||
fn insert_def(&mut self, local: LiveVar, location: Location) {
|
||||
impl LocalUseMapBuild<'_> {
|
||||
fn insert_def(&mut self, local: Local, location: Location) {
|
||||
Self::insert(
|
||||
self.elements,
|
||||
&mut self.local_use_map.first_def_at[local],
|
||||
|
|
@ -107,7 +126,7 @@ impl LocalUseMapBuild<'_, '_> {
|
|||
);
|
||||
}
|
||||
|
||||
fn insert_use(&mut self, local: LiveVar, location: Location) {
|
||||
fn insert_use(&mut self, local: Local, location: Location) {
|
||||
Self::insert(
|
||||
self.elements,
|
||||
&mut self.local_use_map.first_use_at[local],
|
||||
|
|
@ -116,7 +135,7 @@ impl LocalUseMapBuild<'_, '_> {
|
|||
);
|
||||
}
|
||||
|
||||
fn insert_drop(&mut self, local: LiveVar, location: Location) {
|
||||
fn insert_drop(&mut self, local: Local, location: Location) {
|
||||
Self::insert(
|
||||
self.elements,
|
||||
&mut self.local_use_map.first_drop_at[local],
|
||||
|
|
@ -140,13 +159,13 @@ impl LocalUseMapBuild<'_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Visitor<'tcx> for LocalUseMapBuild<'_, '_> {
|
||||
impl Visitor<'tcx> for LocalUseMapBuild<'_> {
|
||||
fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, location: Location) {
|
||||
if let Some(local_with_region) = self.local_use_map.liveness_map.from_local(local) {
|
||||
if self.locals_with_use_data[local] {
|
||||
match categorize(context) {
|
||||
Some(DefUse::Def) => self.insert_def(local_with_region, location),
|
||||
Some(DefUse::Use) => self.insert_use(local_with_region, location),
|
||||
Some(DefUse::Drop) => self.insert_drop(local_with_region, location),
|
||||
Some(DefUse::Def) => self.insert_def(local, location),
|
||||
Some(DefUse::Use) => self.insert_use(local, location),
|
||||
Some(DefUse::Drop) => self.insert_drop(local, location),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ pub(super) fn trace(
|
|||
return;
|
||||
}
|
||||
|
||||
let local_use_map = &LocalUseMap::build(liveness_map, elements, mir);
|
||||
let live_locals: Vec<Local> = liveness_map.to_local.clone().into_iter().collect();
|
||||
let local_use_map = &LocalUseMap::build(&live_locals, elements, mir);
|
||||
|
||||
let cx = LivenessContext {
|
||||
typeck,
|
||||
|
|
@ -59,7 +60,6 @@ pub(super) fn trace(
|
|||
location_table,
|
||||
};
|
||||
|
||||
let live_locals: Vec<Local> = liveness_map.to_local.clone().into_iter().collect();
|
||||
LivenessResults::new(cx).compute_for_all_locals(live_locals);
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ where
|
|||
|
||||
/// Index indicating where each variable is assigned, used, or
|
||||
/// dropped.
|
||||
local_use_map: &'me LocalUseMap<'me>,
|
||||
local_use_map: &'me LocalUseMap,
|
||||
|
||||
/// Maps between a MIR Location and a LocationIndex
|
||||
location_table: &'me LocationTable,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue