Fix optimizer slot clash during inlining and correct closure reduction
order
- Add new_for_inlining to SubstitutionMap to preserve the next_slot
counter, preventing local slot collisions when merging
scopes.
- Update Inliner to request fresh slots for parameters during beta
reduction instead of forcing identity mappings.
- Fix execution order in Optimizer::visit_node for closure inlining
to run prepare_beta_reduction before visiting the function
body, preventing corrupted upvalue captures.
- Fix CLI --no-opt flag to correctly disable the optimizer in the ast
binary.
- Add integration test to prevent future slot clash regressions.
This commit is contained in:
@@ -249,7 +249,7 @@ impl Optimizer {
|
|||||||
&& path.enter_lambda(&callee_opt.identity)
|
&& path.enter_lambda(&callee_opt.identity)
|
||||||
{
|
{
|
||||||
path.inlining_depth += 1;
|
path.inlining_depth += 1;
|
||||||
let mut inner_sub = sub.new_inner();
|
let mut inner_sub = sub.new_for_inlining();
|
||||||
let collapsed = if inliner
|
let collapsed = if inliner
|
||||||
.prepare_beta_reduction(params, &arg_nodes, body, &mut inner_sub)
|
.prepare_beta_reduction(params, &arg_nodes, body, &mut inner_sub)
|
||||||
.is_some()
|
.is_some()
|
||||||
@@ -286,7 +286,7 @@ impl Optimizer {
|
|||||||
&& positional_count.is_some()
|
&& positional_count.is_some()
|
||||||
&& !lambda_node.ty.is_recursive
|
&& !lambda_node.ty.is_recursive
|
||||||
{
|
{
|
||||||
let mut inner_sub = sub.new_inner();
|
let mut inner_sub = sub.new_for_inlining();
|
||||||
path.inlining_stack.insert(*idx);
|
path.inlining_stack.insert(*idx);
|
||||||
path.inlining_depth += 1;
|
path.inlining_depth += 1;
|
||||||
let collapsed = if inliner
|
let collapsed = if inliner
|
||||||
@@ -314,7 +314,7 @@ impl Optimizer {
|
|||||||
&& !closure.function_node.ty.is_recursive
|
&& !closure.function_node.ty.is_recursive
|
||||||
&& path.enter_lambda(&closure.function_node.identity)
|
&& path.enter_lambda(&closure.function_node.identity)
|
||||||
{
|
{
|
||||||
let mut closure_sub = SubstitutionMap::new();
|
let mut closure_sub = sub.new_for_inlining();
|
||||||
for (i, cell) in closure.upvalues.iter().enumerate() {
|
for (i, cell) in closure.upvalues.iter().enumerate() {
|
||||||
closure_sub.add_value(
|
closure_sub.add_value(
|
||||||
Address::Upvalue(UpvalueIdx(i as u32)),
|
Address::Upvalue(UpvalueIdx(i as u32)),
|
||||||
@@ -323,22 +323,16 @@ impl Optimizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
path.inlining_depth += 1;
|
path.inlining_depth += 1;
|
||||||
let inlined_body = self.visit_node(
|
|
||||||
closure.function_node.clone(),
|
|
||||||
&mut closure_sub,
|
|
||||||
path,
|
|
||||||
);
|
|
||||||
|
|
||||||
let collapsed = if inliner
|
let collapsed = if inliner
|
||||||
.prepare_beta_reduction(
|
.prepare_beta_reduction(
|
||||||
&closure.parameter_node,
|
&closure.parameter_node,
|
||||||
&arg_nodes,
|
&arg_nodes,
|
||||||
&inlined_body,
|
&closure.function_node,
|
||||||
&mut closure_sub,
|
&mut closure_sub,
|
||||||
)
|
)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
Some(self.visit_node(inlined_body, &mut closure_sub, path))
|
Some(self.visit_node(closure.function_node.clone(), &mut closure_sub, path))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -128,8 +128,7 @@ impl<'a> Inliner<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Address::Local(slot) = addr {
|
if let Address::Local(slot) = addr {
|
||||||
sub.slot_mapping.insert(*slot, *slot);
|
sub.map_slot(*slot);
|
||||||
sub.next_slot = sub.next_slot.max(slot.0 + 1);
|
|
||||||
}
|
}
|
||||||
*offset += 1;
|
*offset += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ impl SubstitutionMap {
|
|||||||
inner
|
inner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_for_inlining(&self) -> Self {
|
||||||
|
let mut inner = self.new_inner();
|
||||||
|
inner.next_slot = self.next_slot;
|
||||||
|
inner
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_ast_substitution(&mut self, addr: Address, node: AnalyzedNode) {
|
pub fn add_ast_substitution(&mut self, addr: Address, node: AnalyzedNode) {
|
||||||
self.ast_substitutions.insert(addr, Rc::new(node));
|
self.ast_substitutions.insert(addr, Rc::new(node));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user