Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unnecessary boxing of variables that are not reassigned within a closure #56561

Open
aviatesk opened this issue Nov 14, 2024 · 2 comments
Open

Comments

@aviatesk
Copy link
Member

aviatesk commented Nov 14, 2024

In cases like the following code, where a variable defined in the parent scope of a closure is used inside the closure and could potentially be reassigned in the parent scope, it seems to get boxed even if it is never reassigned within the closure itself.

julia> callf(f, a) = f(a);

julia> function demo_box(a)
           x = sin(a)
           x = identity(x)
           callf(a) do a
               a + x
           end
       end;

julia> code_lowered(demo_box, (Float64,))
1-element Vector{Core.CodeInfo}:
 CodeInfo(
1 ─       Core.NewvarNode(:(#18))
│         x@_4 = Core.Box()
│   %3  =   dynamic Main.sin(a)
│   %4  = x@_4
│           builtin Core.setfield!(%4, :contents, %3)
│   %6  = Main.identity
│   %7  = x@_4%8  =   builtin Core.isdefined(%7, :contents)
└──       goto #3 if not %8
2 ─       goto #4
3 ─       Core.NewvarNode(:(x@_5))
└──       x@_5
4%13 = x@_4%14 =   builtin Core.getfield(%13, :contents)
│   %15 =   dynamic (%6)(%14)
│   %16 = x@_4
│           builtin Core.setfield!(%16, :contents, %15)
│   %18 = Main.callf
│   %19 = Main.:(var"#demo_box##8#demo_box##9")
│   %20 = x@_4#18 = %new(%19, %20)%22 = #18%23 =   dynamic (%18)(%22, a)
└──       return %23
)

This boxing appears completely unnecessary to me. Would it be possible to make a simple change to lowering to fix this issue?

@aviatesk
Copy link
Member Author

/cc @JeffBezanson Could I hear your thought on this? I'm sorry if this is a known issue.

@mbauman
Copy link
Member

mbauman commented Nov 14, 2024

I think the challenge is that lowering needs to prove that no re-assignments occur after closure creation, because if any do, then the closure's captured variable needs to be able to be changed. Ref #15276 (comment)

Functions called with the do syntax typically immediately evaluate and discard the anonymous function, but it might escape — possibly even to a global. There's no way lowering could know this.

julia> function demo_box(a)
           x = sin(a)
           f = identity() do a
               a + x
           end
           @show f(1)
           x = 123123
           @show f(1)
       end
demo_box (generic function with 1 method)

julia> demo_box(1.23)
f(1) = 1.9424888019316975
f(1) = 123124

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants