Skip to content

Commit

Permalink
refactor the alias for whole project
Browse files Browse the repository at this point in the history
  • Loading branch information
VaynNecol committed Jan 2, 2025
1 parent 60ce4d3 commit ead2e7a
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 31 deletions.
89 changes: 73 additions & 16 deletions rap/src/analysis/safedrop/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl<'tcx> SafeDropGraph<'tcx> {
let rv_aliaset_idx = self.projection(tcx, true, assign.rv.clone());
match assign.atype {
AssignType::Variant => {
self.values[lv_aliaset_idx].alias[0] = rv_aliaset_idx;
self.alias_set[lv_aliaset_idx] = rv_aliaset_idx;
continue;
}
AssignType::InitBox => {
Expand Down Expand Up @@ -127,9 +127,8 @@ impl<'tcx> SafeDropGraph<'tcx> {
// assign to the variable _x, we will set the birth of _x and its child self.values a new birth.
pub fn fill_birth(&mut self, node: usize, birth: isize) {
self.values[node].birth = birth;
//TODO: check the correctness.
for i in self.values[node].alias.clone() {
if self.values[i].birth == -1 {
for i in 0..self.alias_set.len() {
if self.union_is_same(i, node) && self.values[i].birth == -1 {
self.values[i].birth = birth;
}
}
Expand All @@ -151,14 +150,15 @@ impl<'tcx> SafeDropGraph<'tcx> {
let new_id = self.values.len();
match proj {
ProjectionElem::Deref => {
proj_id = self.values[proj_id].alias[0];
//proj_id = self.values[proj_id].alias[0];
proj_id = self.alias_set[proj_id];
}
/*
* Objective: 2 = 1.0; 0 = 2.0; => 0 = 1.0.0
*/
ProjectionElem::Field(field, ty) => {
if is_right && self.values[proj_id].alias[0] != proj_id {
proj_id = self.values[proj_id].alias[0];
if is_right && self.alias_set[proj_id] != proj_id {
proj_id = self.alias_set[proj_id];
local = self.values[proj_id].local;
}
let field_idx = field.as_usize();
Expand All @@ -172,6 +172,8 @@ impl<'tcx> SafeDropGraph<'tcx> {
node.birth = self.values[proj_id].birth;
node.field_id = field_idx;
self.values[proj_id].fields.insert(field_idx, node.index);
self.alias_set.push(self.values.len());
self.dead_record.push(false);
self.values.push(node);
}
proj_id = *self.values[proj_id].fields.get(&field_idx).unwrap();
Expand All @@ -184,12 +186,14 @@ impl<'tcx> SafeDropGraph<'tcx> {

//instruction to assign alias for a variable.
pub fn merge_alias(&mut self, lv: usize, rv: usize) {
if self.values[lv].alias.len() > 1 {
let mut alias_clone = self.values[rv].alias.clone();
self.values[lv].alias.append(&mut alias_clone);
} else {
self.values[lv].alias = self.values[rv].alias.clone();
}
// if self.values[lv].alias.len() > 1 {
// let mut alias_clone = self.values[rv].alias.clone();
// self.values[lv].alias.append(&mut alias_clone);
// } else {
// self.values[lv].alias = self.values[rv].alias.clone();
// }
self.union_merge(lv, rv);

for field in self.values[rv].fields.clone().into_iter() {
if !self.values[lv].fields.contains_key(&field.0) {
let mut node = ValueNode::new(
Expand All @@ -202,12 +206,15 @@ impl<'tcx> SafeDropGraph<'tcx> {
node.birth = self.values[lv].birth;
node.field_id = field.0;
self.values[lv].fields.insert(field.0, node.index);
self.alias_set.push(self.values.len());
self.dead_record.push(false);
self.values.push(node);
}
let lv_field = *(self.values[lv].fields.get(&field.0).unwrap());
self.merge_alias(lv_field, field.1);
}
}

//inter-procedure instruction to merge alias.
pub fn merge(&mut self, ret_alias: &RetAlias, arg_vec: &Vec<usize>) {
if ret_alias.left_index >= arg_vec.len() || ret_alias.right_index >= arg_vec.len() {
Expand All @@ -227,27 +234,77 @@ impl<'tcx> SafeDropGraph<'tcx> {
node.birth = self.values[lv].birth;
node.field_id = *index;
self.values[lv].fields.insert(*index, node.index);
self.alias_set.push(self.values.len());
self.dead_record.push(false);
self.values.push(node);
}
lv = *self.values[lv].fields.get(&index).unwrap();
}
for index in ret_alias.right_field_seq.iter() {
if self.values[rv].alias[0] != rv {
rv = self.values[rv].alias[0];
// if self.values[rv].alias[0] != rv {
if self.union_is_same(rv, self.alias_set[rv]) {
rv = self.values[rv].index;
right_init = self.values[rv].local;
}
if self.values[rv].fields.contains_key(&index) == false {
if !self.values[rv].fields.contains_key(&index) {
let need_drop = ret_alias.right_need_drop;
let may_drop = ret_alias.right_may_drop;
let mut node = ValueNode::new(self.values.len(), right_init, need_drop, may_drop);
node.kind = TyKind::RawPtr;
node.birth = self.values[rv].birth;
node.field_id = *index;
self.values[rv].fields.insert(*index, node.index);
self.alias_set.push(self.values.len());
self.dead_record.push(false);
self.values.push(node);
}
rv = *self.values[rv].fields.get(&index).unwrap();
}
self.merge_alias(lv, rv);
}

#[inline]
pub fn union_find(&mut self, e: usize) -> usize {
let mut r = e;
while self.alias_set[r] != r {
r = self.alias_set[r];
}
r
}

#[inline]
pub fn union_merge(&mut self, e1: usize, e2: usize) {
let f1 = self.union_find(e1);
let f2 = self.union_find(e2);

if f1 < f2 {
self.alias_set[f2] = f1;
}
if f1 > f2 {
self.alias_set[f1] = f2;
}

for member in 0..self.alias_set.len() {
self.alias_set[member] = self.union_find(self.alias_set[member]);
}
}

#[inline]
pub fn union_is_same(&mut self, e1: usize, e2: usize) -> bool {
let f1 = self.union_find(e1);
let f2 = self.union_find(e2);
f1 == f2
}

pub fn union_has_alias(&mut self, e: usize) -> bool {
for i in 0..self.alias_set.len() {
if i == e {
continue;
}
if self.union_is_same(e, i) {
return true;
}
}
false
}
}
40 changes: 30 additions & 10 deletions rap/src/analysis/safedrop/check_bugs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,31 @@ impl<'tcx> SafeDropGraph<'tcx> {
}
}

pub fn exist_dead(&self, node: usize, record: &mut FxHashSet<usize>, dangling: bool) -> bool {
pub fn exist_dead(
&mut self,
node: usize,
record: &mut FxHashSet<usize>,
dangling: bool,
) -> bool {
//if is a dangling pointer check, only check the pointer type varible.
if self.values[node].is_alive() == false
&& (dangling && self.values[node].is_ptr() || !dangling)
{
return true;
}
record.insert(node);
if self.values[node].alias[0] != node {
for i in self.values[node].alias.clone().into_iter() {
if i != node && record.contains(&i) == false && self.exist_dead(i, record, dangling)
{
if self.union_has_alias(node) {
// for i in self.values[node].alias.clone().into_iter() {
// if i != node && record.contains(&i) == false && self.exist_dead(i, record, dangling)
// {
// return true;
// }
// }
for i in 0..self.alias_set.len() {
if i != node && !self.union_is_same(i, node) {
continue;
}
if record.contains(&i) == false && self.exist_dead(i, record, dangling) {
return true;
}
}
Expand All @@ -65,7 +78,7 @@ impl<'tcx> SafeDropGraph<'tcx> {
return false;
}

pub fn is_dangling(&self, local: usize) -> bool {
pub fn is_dangling(&mut self, local: usize) -> bool {
let mut record = FxHashSet::default();
return self.exist_dead(local, &mut record, local != 0);
}
Expand Down Expand Up @@ -109,13 +122,20 @@ impl<'tcx> SafeDropGraph<'tcx> {
return;
}
//check if there is a double free bug.
if self.df_check(drop, info.span) {
if !alias && self.df_check(drop, info.span) {
return;
}
if self.dead_record[drop] { return; } else { self.dead_record[drop] = true; }
//drop their alias
if self.values[drop].alias[0] != drop {
for i in self.values[drop].alias.clone().into_iter() {
if self.values[i].is_ref() {
if self.alias_set[drop] != drop {
// for i in self.values[drop].alias.clone().into_iter() {
// if self.values[i].is_ref() {
// continue;
// }
// self.dead_node(i, birth, info, true);
// }
for i in 0..self.alias_set.len() {
if !self.union_is_same(drop, i) || i == drop || self.values[i].is_ref() {
continue;
}
self.dead_node(i, birth, info, true);
Expand Down
12 changes: 10 additions & 2 deletions rap/src/analysis/safedrop/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ pub struct ValueNode {
pub kind: TyKind,
pub father: usize,
pub field_id: usize, // the field id of its father node.
pub alias: Vec<usize>,
pub birth: isize,
pub fields: FxHashMap<usize, usize>,
}
Expand All @@ -111,7 +110,6 @@ impl ValueNode {
need_drop: need_drop,
father: local,
field_id: usize::MAX,
alias: vec![index],
birth: 0,
may_drop: may_drop,
kind: TyKind::Adt,
Expand Down Expand Up @@ -163,6 +161,8 @@ pub struct SafeDropGraph<'tcx> {
pub bug_records: BugRecords,
// a threhold to avoid path explosion.
pub visit_times: usize,
pub alias_set: Vec<usize>,
pub dead_record: Vec<bool>,
// analysis of heap item
pub adt_owner: AdtOwner,
}
Expand All @@ -178,6 +178,8 @@ impl<'tcx> SafeDropGraph<'tcx> {
let locals = &body.local_decls;
let arg_size = body.arg_count;
let mut values = Vec::<ValueNode>::new();
let mut alias = Vec::<usize>::new();
let mut dead = Vec::<bool>::new();
let param_env = tcx.param_env(def_id);
for (local, local_decl) in locals.iter_enumerated() {
let need_drop = local_decl.ty.needs_drop(tcx, param_env); // the type is drop
Expand All @@ -189,6 +191,8 @@ impl<'tcx> SafeDropGraph<'tcx> {
need_drop || may_drop,
);
node.kind = kind(local_decl.ty);
alias.push(values.len());
dead.push(false);
values.push(node);
}

Expand Down Expand Up @@ -273,6 +277,8 @@ impl<'tcx> SafeDropGraph<'tcx> {
lvl0.birth = values[lv_local].birth;
lvl0.field_id = 0;
values[lv_local].fields.insert(0, lvl0.index);
alias.push(values.len());
dead.push(false);
values.push(lvl0);
}
match x {
Expand Down Expand Up @@ -470,6 +476,8 @@ impl<'tcx> SafeDropGraph<'tcx> {
return_set: FxHashSet::default(),
bug_records: BugRecords::new(),
visit_times: 0,
alias_set: alias,
dead_record: dead,
adt_owner,
}
}
Expand Down
14 changes: 11 additions & 3 deletions rap/src/analysis/safedrop/safedrop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,14 @@ impl<'tcx> SafeDropGraph<'tcx> {
/* duplicate the status before visiting a path; */
let backup_values = self.values.clone(); // duplicate the status when visiting different paths;
let backup_constant = self.constant.clone();
let backup_alias_set = self.alias_set.clone();
let backup_dead = self.dead_record.clone();
self.check(bb_index, tcx, fn_map);
/* restore after visit */
self.values = backup_values;
self.constant = backup_constant;
self.alias_set = backup_alias_set;
self.dead_record = backup_dead;
}
pub fn split_check_with_cond(
&mut self,
Expand All @@ -92,12 +96,16 @@ impl<'tcx> SafeDropGraph<'tcx> {
/* duplicate the status before visiting a path; */
let backup_values = self.values.clone(); // duplicate the status when visiting different paths;
let backup_constant = self.constant.clone();
let backup_alias_set = self.alias_set.clone();
let backup_dead = self.dead_record.clone();
/* add control-sensitive indicator to the path status */
self.constant.insert(path_discr_id, path_discr_val);
self.check(bb_index, tcx, fn_map);
/* restore after visit */
self.values = backup_values;
self.constant = backup_constant;
self.alias_set = backup_alias_set;
self.dead_record = backup_dead;
}

// the core function of the safedrop.
Expand Down Expand Up @@ -158,12 +166,12 @@ impl<'tcx> SafeDropGraph<'tcx> {
match discr {
Copy(p) | Move(p) => {
let place = self.projection(tcx, false, p.clone());
if let Some(constant) = self.constant.get(&self.values[place].alias[0]) {
if let Some(constant) = self.constant.get(&self.values[place].index) {
single_target = true;
sw_val = *constant;
}
if self.values[place].alias[0] != place {
path_discr_id = self.values[place].alias[0];
if self.values[place].index != place {
path_discr_id = self.values[place].index;
sw_targets = Some(targets.clone());
}
}
Expand Down

0 comments on commit ead2e7a

Please sign in to comment.