Skip to content

Commit

Permalink
Use defined function index when guarding against recursive inlining
Browse files Browse the repository at this point in the history
We were mistakenly using the regular function index, which is the same when
there are zero imported functions, so our existing test passed.
  • Loading branch information
fitzgen committed Oct 18, 2023
1 parent a74ae23 commit 22dc70e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
12 changes: 5 additions & 7 deletions src/optimize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -786,24 +786,22 @@ impl Optimizer {

// ... and if that function index is not already on our winlining stack
// (i.e. we aren't in a recursive inlining chain)...
if on_stack.contains(&callee_func_index) {
let defined_func_index = callee_func_index
.checked_sub(context.num_imported_funcs)
.unwrap();
if on_stack.contains(&defined_func_index) {
return Ok(None);
}

// ... and if that function has the correct type (if this is not true
// then either the profile is bogus/mismatched or every time the call
// site was executed it trapped)...
if context.funcs[usize::try_from(callee_func_index - context.num_imported_funcs).unwrap()]
!= type_index
{
if context.funcs[usize::try_from(defined_func_index).unwrap()] != type_index {
return Ok(None);
}

// ... then we can winline this callee and push it onto our stack!

let defined_func_index = callee_func_index
.checked_sub(context.num_imported_funcs)
.unwrap();
let locals_delta = *num_locals;
let func_body = context.func_bodies[usize::try_from(defined_func_index).unwrap()].clone();
let ops = func_body
Expand Down
38 changes: 38 additions & 0 deletions tests/all/optimize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,44 @@ fn dont_inline_direct_recursion() -> Result<()> {
)
}

#[test]
fn dont_inline_direct_recursion_with_imports() -> Result<()> {
assert_optimize(
Optimizer::new().min_total_calls(100),
&[&[(1, 100)]],
r#"
(module
(type (func (param i32) (result i32)))
(import "foo" "bar" (func (type 0)))
(func (type 0)
local.get 0
local.get 0
call_indirect (type 0)
)
(table 100 100 funcref)
(elem (i32.const 0) funcref (ref.func 1))
)
"#,
r#"
(module
(type (;0;) (func (param i32) (result i32)))
(import "foo" "bar" (func (;0;) (type 0)))
(func (;1;) (type 0) (param i32) (result i32)
(local i32)
local.get 0
local.get 0
call_indirect (type 0)
)
(table (;0;) 100 100 funcref)
(elem (;0;) (i32.const 0) funcref (ref.func 1))
)
"#,
)
}

#[test]
fn multiple_funcref_tables() -> Result<()> {
assert_optimize(
Expand Down

0 comments on commit 22dc70e

Please sign in to comment.