Refactor optimizer to track upvalue usage
The `UsageInfo` struct has been updated to include tracking for `used_upvalues` and `assigned_upvalues`. The `collect_usage` function has been modified to handle these new fields when encountering `Address::Upvalue`. The `map_params_to_args` function now takes `body_usage` as an argument to ensure that parameters assigned to or used in the body are correctly substituted. A new helper function, `collect_parameter_slots_set`, has been added to gather all parameter slots within a pattern. The inlining logic in `Optimizer::inline_call` has been enhanced to prevent inlining if a parameter is used or assigned in the function body but cannot be substituted. This addresses a bug where aggressive inlining could lead to incorrect code generation when parameters were reassigned. A new integration test, `test_closure_reassignment_optimization_bug`, has been added to specifically target and verify the fix for this inlining issue.
This commit is contained in:
@@ -390,4 +390,15 @@ mod tests {
|
||||
"[\"Symbol:\" \"btc\" \"field:\" :close \"id:\" \"cls\"]"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_closure_reassignment_optimization_bug() {
|
||||
let env = Environment::new();
|
||||
// This test case reproduces a bug where the optimizer aggressively inlined a function
|
||||
// ('f') even though its parameters ('x') were being assigned to in the body (by inner lambda).
|
||||
// The fix ensures that such functions are NOT inlined.
|
||||
let source = "(do (def f (fn [[x y]] (fn [] (assign x (+ x y))))) ((f [1 2])))";
|
||||
let res = env.run_script(source);
|
||||
assert_eq!(format!("{}", res.unwrap()), "3");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user