escape analysis: fixed some bugs regarding imprecise local

escape-analysis
pca006132 2022-04-08 20:16:48 +08:00
parent fb79b47b38
commit ea5a8c95dc
2 changed files with 36 additions and 18 deletions

View File

@ -37,7 +37,7 @@ pub struct BasicBlockId(usize);
pub enum LifetimeIR {
VarAssign { var: StrRef, lifetime: LifetimeId },
VarAccess { var: StrRef },
FieldAssign { obj: LifetimeId, field: StrRef, new: LifetimeId },
FieldAssign { obj: LifetimeId, field: StrRef, new: LifetimeId, is_init: bool },
FieldAccess { obj: LifetimeId, field: StrRef },
CreateLifetime { kind: LifetimeKind },
PassedToFunc { param_lifetimes: Vec<LifetimeId> },
@ -123,7 +123,7 @@ impl LifetimeIRBuilder {
LifetimeIR::Branch { targets } => {
destination_mapping.insert(i, targets);
}
_ => ()
_ => (),
}
}
}
@ -339,14 +339,23 @@ impl<'a> LifetimeAnalyzer<'a> {
self.lifetime_stores.remove(rhs_id);
}
fn get_field_lifetime(&self, obj: LifetimeId, field: StrRef) -> LifetimeId {
fn get_field_lifetime(&mut self, obj: LifetimeId, field: StrRef) -> LifetimeId {
use LifetimeKind::*;
let id = *self.lifetime_to_id.get(&obj).unwrap();
let store = &self.lifetime_stores.get(id).unwrap();
if let Some(lifetime) = store.fields.get(&field) {
*lifetime
} else if matches!(store.kind, PreciseLocal | ImpreciseLocal) {
LifetimeId(0)
let store = self.lifetime_stores.get(id).unwrap();
if matches!(store.kind, PreciseLocal | ImpreciseLocal) {
if let Some(&lifetime) = store.fields.get(&field) {
let field_lifetime_kind = self.get_lifetime_kind(lifetime);
if field_lifetime_kind == PreciseLocal
&& (store.kind == ImpreciseLocal || field == "$elem".into())
{
let id = *self.lifetime_to_id.get(&lifetime).unwrap();
self.lifetime_stores.get_mut(id).unwrap().to_mut().kind = ImpreciseLocal;
}
lifetime
} else {
LifetimeId(0)
}
} else {
obj
}
@ -357,6 +366,7 @@ impl<'a> LifetimeAnalyzer<'a> {
obj: LifetimeId,
field: StrRef,
field_lifetime: LifetimeId,
is_init: bool,
) -> Result<(), String> {
use LifetimeKind::*;
let obj_id = *self.lifetime_to_id.get(&obj).unwrap();
@ -377,15 +387,15 @@ impl<'a> LifetimeAnalyzer<'a> {
}
PreciseLocal | ImpreciseLocal => {
// weak update
let old_lifetime = obj_store
.to_mut()
.fields
.get(&field)
.copied();
let old_lifetime = obj_store.to_mut().fields.get(&field).copied();
if let Some(old_lifetime) = old_lifetime {
self.unify(old_lifetime, field_lifetime);
} else {
obj_store.to_mut().fields.insert(field, field_lifetime);
if !is_init {
// unify with unknown lifetime
self.unify(LifetimeId(0), field_lifetime);
}
}
}
_ => (),
@ -455,8 +465,8 @@ impl<'a> LifetimeAnalyzer<'a> {
self.add_lifetime(id, LifetimeKind::Static)
}
}
FieldAssign { obj, field, new } => {
self.set_field_lifetime(*obj, *field, *new)
FieldAssign { obj, field, new, is_init } => {
self.set_field_lifetime(*obj, *field, *new, *is_init)
.map_err(|e| format!("{} in {}", e, loc))?;
}
FieldAccess { obj, field } => {
@ -490,7 +500,7 @@ impl<'a> LifetimeAnalyzer<'a> {
}
return Ok(None);
}
Branch { targets } => return Ok(Some(targets))
Branch { targets } => return Ok(Some(targets)),
}
}
Ok(None)

View File

@ -153,6 +153,7 @@ impl<'a> EscapeAnalyzer<'a> {
obj: list_lifetime,
field: "$elem".into(),
new: elem_lifetime,
is_init: true,
},
loc,
);
@ -165,6 +166,7 @@ impl<'a> EscapeAnalyzer<'a> {
obj: list_lifetime,
field: "$elem".into(),
new: elem_lifetime,
is_init: true,
},
loc,
);
@ -183,6 +185,7 @@ impl<'a> EscapeAnalyzer<'a> {
obj: tuple_lifetime,
field: format!("$elem{}", i).into(),
new: lifetime,
is_init: true,
},
loc,
);
@ -208,6 +211,7 @@ impl<'a> EscapeAnalyzer<'a> {
obj: slice_lifetime,
field: "$elem".into(),
new: slice_elem,
is_init: true
},
loc,
);
@ -249,7 +253,9 @@ impl<'a> EscapeAnalyzer<'a> {
}
match &func.node {
ExprKind::Name { id, .. } => {
self.builder.append_ir(PassedToFunc { param_lifetimes: lifetimes }, loc);
if !lifetimes.is_empty() {
self.builder.append_ir(PassedToFunc { param_lifetimes: lifetimes }, loc);
}
if need_alloca {
let id = self
.resolver
@ -342,6 +348,7 @@ impl<'a> EscapeAnalyzer<'a> {
obj: list_lifetime,
field: "$elem".into(),
new: elem_lifetime,
is_init: true
},
elt.location,
);
@ -365,7 +372,7 @@ impl<'a> EscapeAnalyzer<'a> {
let value_lifetime = self.handle_expr(value)?.unwrap();
if let Some(field_lifetime) = rhs_lifetime {
self.builder.append_ir(
FieldAssign { obj: value_lifetime, field: *attr, new: field_lifetime },
FieldAssign { obj: value_lifetime, field: *attr, new: field_lifetime, is_init: false },
lhs.location,
);
}
@ -396,6 +403,7 @@ impl<'a> EscapeAnalyzer<'a> {
obj: value_lifetime,
field: "$elem".into(),
new: elem_lifetime,
is_init: false
},
lhs.location,
);