Skip to content

Commit

Permalink
Efficient solution implemented! All tests pass
Browse files Browse the repository at this point in the history
  • Loading branch information
Swathi Narayan committed Jul 19, 2024
1 parent b56b7b0 commit bdb4bbb
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 161 deletions.
118 changes: 11 additions & 107 deletions crates/forge_analyzer/src/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,96 +230,6 @@ pub fn run_resolver(
};
module.visit_with(&mut collector);
}
// This loop iterates through env's bodies and recreates an updated set of bodies to satisfy SSA form of IR dump.
let mut new_funcs: TiVec<FuncId, Body> = TiVec::new();
// Structures used in the loop - initialized here for reuse per each body.
let mut temp = HashSet::new();
let mut non_local_vars = HashMap::new();
let mut updated_vars = HashMap::new();
// Iterates through the bodies in the environment
for (func_id, body) in environment.bodies().enumerate() {
let mut new_body = body.clone();
let vars = &body.vars;
// Make a new structure to hold all global ids
for var_id in vars.keys() {
// Add to set of globals if VarKind is global reference, temp, ret, or arg
let varkind = vars.get(var_id).unwrap();
match varkind {
VarKind::GlobalRef(defid) | VarKind::Arg(defid) => {
temp.insert(var_id);
non_local_vars.insert(var_id, varkind);
}
VarKind::Temp { parent } => {
temp.insert(var_id);
non_local_vars.insert(var_id, varkind);
}
VarKind::Ret => {
temp.insert(var_id);
non_local_vars.insert(var_id, varkind);
}
_ => {}
}
}
// new_body.clear_non_local_vars();

// Parse through the blocks within the body:
let blocks = &body.blocks;
// For every "Assign" statement, there must be a global reference that matches it
for blockid in blocks.keys() {
let blockiter = blocks.get(blockid).into_iter();
for block in blockiter {
let insts = &block.insts;
let mut new_insts: Vec<Inst> = Vec::new();
for inst in insts.iter() {
// Instructions that are assign statements must be updated with new VarId reference:
if let Inst::Assign(variable, rvalue) = inst {
// Parse and update the rvalue to have correct VarId references:
let new_rvalue = update_rvalue(rvalue, &updated_vars);

let var_id = variable.as_var_id().unwrap();

// EXISTING CASE:
// If this VarId exists in globals, then remove to reflect that this assign statement has a corresp. global ref, and add updated instruction.
if temp.contains(&var_id) {
temp.remove(&var_id);
new_insts.insert(
new_insts.len(),
Inst::Assign(variable.clone(), new_rvalue),
);
}
// NEW CASE:
// If one does not exist: Make a copy of the previous global ref (this is guaranteed to exist), and add updated instruction to set of instructions.
else {
// Extract VarKind(DefId) for this VarId from the globals map, and add Var to body.
let var_kind = (*non_local_vars.get(&var_id).unwrap()).clone();
let new_var_id = new_body.add_var(var_kind);
let new_inst = Inst::Assign(Variable::from(new_var_id), new_rvalue);
new_insts.insert(new_insts.len(), new_inst);
// Update the def_id_to_locals value, to reflect the new VarId assignment to this global ref.
let def_id = new_body.get_defid_from_var(new_var_id).unwrap();
new_body.update_global(def_id, new_var_id);

// Update our updated_vars map with the new {old VarId -> new VarId} mapping for later references.
updated_vars.insert(var_id, new_var_id);
}
// If instruction is of type Expression, we simply add the instruction to set of instructions.
} else if let Inst::Expr(rvalue) = inst {
new_insts.insert(new_insts.len(), inst.clone());
}
}
// Add set of instructions to updated Body of environment
new_body.add_insts(new_insts, blockid);
}
}
// Add updated body to new set of functions
new_funcs.insert(FuncId(func_id as u32), new_body);
// Clear all used structures:
temp.clear();
non_local_vars.clear();
updated_vars.clear();
}
// Update environment with new structures created
environment.defs.funcs = new_funcs;
environment
}

Expand Down Expand Up @@ -1242,7 +1152,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
Pat::Ident(BindingIdent { id, .. }) => {
let id = id.to_id();
let def = self.res.get_or_insert_sym(id, self.module);
let var = self.body.get_or_insert_global(def);
let var = self.body.insert_global(def);
self.push_curr_inst(Inst::Assign(
Variable::new(var),
Rvalue::Read(Operand::Var(rhs)),
Expand Down Expand Up @@ -1293,7 +1203,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
let id = key.to_id();
rhs.projections.push(Projection::Known(id.0.clone()));
let def = self.res.get_or_insert_sym(id, self.module);
let var = self.body.get_or_insert_global(def);
let var = self.body.insert_global(def);
self.push_curr_inst(Inst::Assign(
Variable::new(var),
Rvalue::Read(Operand::Var(rhs)),
Expand Down Expand Up @@ -1340,7 +1250,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
.iter()
.find(|(name, defid)| name == "constructor")
{
let var = self.body.get_or_insert_global(*def_constructor);
let var = self.body.insert_global(*def_constructor);
return Operand::with_var(var);
}
}
Expand All @@ -1354,7 +1264,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
.iter()
.find(|(name, defid)| name == &ident.sym)
{
let var = self.body.get_or_insert_global(*def_constructor);
let var = self.body.insert_global(*def_constructor);
return Operand::with_var(var);
}
}
Expand Down Expand Up @@ -1430,7 +1340,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
Pat::Ident(BindingIdent { id, .. }) => {
let id = id.to_id();
let def = self.res.get_or_insert_sym(id, self.module);
let var = self.body.get_or_insert_global(def);
let var = self.body.insert_global(def);
self.push_curr_inst(Inst::Assign(Variable::new(var), val));
}
Pat::Array(ArrayPat { elems, .. }) => {
Expand Down Expand Up @@ -1499,7 +1409,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
}
Expr::Ident(ident) => {
let defid = self.res.sym_to_id(ident.to_id(), self.module);
let varid = self.body.get_or_insert_global(defid.unwrap());
let varid = self.body.insert_global(defid.unwrap());
self.body.push_tmp(
self.block,
Rvalue::Call(Operand::Var(Variable::from(varid)), SmallVec::default()),
Expand Down Expand Up @@ -1542,7 +1452,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
warn!("unknown symbol: {}", id.0);
return Literal::Undef.into();
};
let var = self.body.get_or_insert_global(def);
let var = self.body.insert_global(def);
Operand::with_var(var)
}

Expand All @@ -1562,7 +1472,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
warn!("unknown symbol: {}", id.0);
return Literal::Undef.into();
};
let var = self.body.get_or_insert_global(def);
let var = self.body.insert_global(def);
Operand::with_var(var)
}
JSXElementName::JSXMemberExpr(mem) => self.lower_jsx_member(mem),
Expand All @@ -1572,7 +1482,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
warn!("unknown symbol: {}", ns.0);
return Literal::Undef.into();
};
let var = self.body.get_or_insert_global(def);
let var = self.body.insert_global(def);
let mut var = Variable::new(var);
var.projections.push(Projection::Known(name.sym.clone()));
Operand::Var(var)
Expand Down Expand Up @@ -1612,7 +1522,7 @@ impl<'cx> FunctionAnalyzer<'cx> {
let id = ident.to_id();
let new_def =
self.res.get_or_insert_sym(id.clone(), self.module);
let var_id = self.body.get_or_insert_global(new_def);
let var_id = self.body.insert_global(new_def);
var.projections.push(Projection::Known(ident.sym.clone()));
self.res
.def_mut(def_id)
Expand Down Expand Up @@ -2117,7 +2027,7 @@ impl Visit for ArgDefiner<'_> {
.res
.get_or_overwrite_sym(id.clone(), self.module, DefRes::Arg);
self.res.add_parent(defid, self.func);
let var = self.body.get_or_insert_global(defid);
let var = self.body.insert_global(defid);
self.body.push_assign(
STARTING_BLOCK,
var.into(),
Expand Down Expand Up @@ -3456,12 +3366,6 @@ impl Environment {
self.defs.funcs.iter()
}

// Mutable iterator
#[inline]
pub fn bodies_mut(&mut self) -> impl Iterator<Item = &mut Body> + '_ {
self.defs.funcs.iter_mut()
}

#[inline]
pub fn get_object(&self, mod_id: ModId, object_id: Id) -> Option<&Class> {
let def_id = self.get_sym(object_id, mod_id)?;
Expand Down
24 changes: 0 additions & 24 deletions crates/forge_analyzer/src/interp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ pub trait Dataflow<'cx>: Sized {
rvalue: &'cx Rvalue,
initial_state: Self::State,
) -> Self::State {
// println!("hi");
match rvalue {
Rvalue::Intrinsic(intrinsic, args) => self.transfer_intrinsic(
interp,
Expand Down Expand Up @@ -419,15 +418,9 @@ impl ValueManager {
projection_vec: ProjectionVec,
value: Value,
) {
// println!("Attempting to insert: defid - {:?} varid - {:?} proj vec - {:?} val - {:?}", def_id_func, var_id, projection_vec[0], value);
// println!("Current var mapping with projects: {:?}", self.varid_to_value_with_proj);
// println!("Current var mapping with values: {:?}", self.varid_to_value);
if projection_vec.is_empty() {
// println!("EMPTY!");
self.varid_to_value.insert((def_id_func, var_id), value);
} else {
// println!("NOT EMPTY");
// DOES NOT FIX:
self.varid_to_value_with_proj
.insert((def_id_func, var_id, projection_vec), value);
}
Expand Down Expand Up @@ -606,22 +599,13 @@ impl<'cx, C: Runner<'cx>> Interp<'cx, C> {
value: Value,
projections: ProjectionVec,
) {
// println!("In add val with proj: Adding new value defid - {:?} varid - {:?} proj vec - {:?} val - {:?}", defid_block, varid, projections, value);
// println!("Add val with projection: {:?}", value);
let (varid, projections) = self.get_farthest_obj(defid_block, varid, projections);
self.value_manager
.insert_var_with_projection(defid_block, varid, projections, value);
}

// this function takes in an operand checks for previous values and returns a value optional
//
// SW: This function adds a value to a definition,
// with the input of a DefId, the locator value (points to memory location), and the read value (value to be read).
// There are 4 cases - if the existing value
#[inline]
pub fn add_value_to_definition(&mut self, defid_block: DefId, lval: Variable, rvalue: Rvalue) {
// println!("Entered add val to def function with defid - {:?}, lval - {:?}, rval - {:?}", defid_block, lval, rvalue);
// println!("Add val to def: {:?}", rvalue);
if let Variable {
base: Base::Var(varid),
projections,
Expand All @@ -633,8 +617,6 @@ impl<'cx, C: Runner<'cx>> Interp<'cx, C> {
.get_value(defid_block, varid, Some(projections.clone()))
.cloned()
{
// println!("The existing value: {:?}", existing_lval);
// println!("The (current) real value: {:?}", rval_value);
// if there is an existing value...
match (existing_lval, rval_value) {
// return unknown if either values are unknown
Expand All @@ -650,10 +632,8 @@ impl<'cx, C: Runner<'cx>> Interp<'cx, C> {
projections,
),
// push other const onto phi vec if either are const and phi
// SW: NEED TO MODIFY THIS CASE TO HANDLE REASSIGNMENTS. Hits if we do a reassignment after already having done one.
(Value::Const(const_value), Value::Phi(phi_value))
| (Value::Phi(phi_value), Value::Const(const_value)) => {
// println!("Entered constant and phi vec match case");
let mut new_phi = phi_value;
new_phi.push(const_value);
self.add_value_with_projection(
Expand All @@ -664,20 +644,17 @@ impl<'cx, C: Runner<'cx>> Interp<'cx, C> {
)
}
// push consts into vec if both are consts
// SW: NEED TO MODIFY THIS CASE TO HANDLE REASSIGNMENTS. Hits if we do a single reassignment.
(Value::Const(const_value1), Value::Const(const_value2)) => {
self.add_value_with_projection(
defid_block,
varid,
Value::Phi(vec![const_value1, const_value2]),
projections,
);
// println!("Entered double constant match case");
}
(Value::Object(exist_var), Value::Object(new_var)) => {
// store projection values that are transferred
let mut projections_transferred = vec![];
// println!("In add val to def - projections transferred are: {:?}", projections_transferred);
// transfer all projection values from the new_var into the existing var
let start_new = (defid_block, new_var, ProjectionVec::new());
let query_new = match new_var.0.checked_add(1) {
Expand Down Expand Up @@ -728,7 +705,6 @@ impl<'cx, C: Runner<'cx>> Interp<'cx, C> {
}
} else {
// push the rval if no existing value
// println!("No existing value");
self.add_value_with_projection(defid_block, varid, rval_value, projections)
}
}
Expand Down
39 changes: 10 additions & 29 deletions crates/forge_analyzer/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,26 +339,6 @@ impl Body {
self.owner
}

// This function clears the non local definition variables in the vars of this body.
// Written to supports the SSA Form fix.
#[inline]
pub(crate) fn clear_non_local_vars(&mut self) {
println!("OLD VARS: {:?}", self.vars);
let mut new_vars = self.vars.clone();
new_vars.clear();

for (_, varkind) in self.vars.iter_mut_enumerated() {
match varkind {
VarKind::LocalDef(_) | VarKind::Ret => {
_ = new_vars.push_and_get_key(varkind.clone());
}
_ => {}
}
}
println!("NEW VARS: {:?}", new_vars);
self.vars = new_vars;
}

#[inline]
pub(crate) fn add_var(&mut self, kind: VarKind) -> VarId {
self.vars.push_and_get_key(kind)
Expand Down Expand Up @@ -396,22 +376,23 @@ impl Body {
var_id
}

// This function returns the varId that maps to the input defId,
// or creates a new mapping of type global reference with the input defId and new varId.
#[inline]
// Given an input DefId, inserts new entry and returns created VarId.
// Used for when vars are initialized or reassigned a new value.
pub(crate) fn insert_global(&mut self, def: DefId) -> VarId {
let var_id = self.vars.push_and_get_key(VarKind::GlobalRef(def));
self.def_id_to_vars.insert(def, var_id);
var_id
}

// Given an input DefId, gets corresponding VarId or adds new entry and returns created VarId.
// Used to get vars already defined (or args passed in) on the right hand of equal sign.
pub(crate) fn get_or_insert_global(&mut self, def: DefId) -> VarId {
*self
.def_id_to_vars
.entry(def)
.or_insert_with(|| self.vars.push_and_get_key(VarKind::GlobalRef(def)))
}

// This function updates the existing DefId -> VarId mapping with the input values, or inserts new if one doesn't exist.
#[inline]
pub(crate) fn update_global(&mut self, def: DefId, var: VarId) {
self.def_id_to_vars.insert(def, var);
}

#[inline]
pub(crate) fn new_block(&mut self) -> BasicBlockId {
self.blocks.push_and_get_key(BasicBlock::default())
Expand Down
10 changes: 9 additions & 1 deletion test-apps/basic/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ function var_reref() {
c = 2 * b;
}


const App = () => {

let testObjectOther = {
Expand All @@ -59,6 +58,15 @@ const App = () => {
}
}

let value = "value"

let h = { headers: { authorization: "test" } }
h.headers.authorization = process.env.SECRET
h.headers.authorization = `test ${value}`


fetch("url", h)

foo();
test_function("test_word");
testFn();
Expand Down

0 comments on commit bdb4bbb

Please sign in to comment.