-
Notifications
You must be signed in to change notification settings - Fork 5.4k
ZJIT: Implement getlocal and setlocal (for nested scopes) #13689
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
Conversation
EDIT: fixed |
This comment has been minimized.
This comment has been minimized.
Also added 2 minor cleanups. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good -- some comments
1.times do |l2| | ||
1.times do |l1| | ||
define_method(:test) do | ||
l1 = 1 | ||
l2 = 2 | ||
l3 = 3 | ||
[l1, l2, l3] | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR adds support for the inner functions to write to outer locals but it doesn't look like it modifies those outer functions to handle their locals being written to
What I mean is if you read from l2
in the outer 1.times
loop, you will see a getlocal_WC_0
which we have folded away in our bytecode->IR pass. In other words, we'll miss the fact that the inner function writes to the frame.
I think this happens to "work" accidentally right now because we abort compiling if we have send with block (Send
) and therefore never have a JIT compiled function have its locals modified like this.
Since block ISEQs are known statically, we can/should detect this kind of nested scope local writing in the block ISEQs and penalize the locals in the upper frame(s) that might get written to like this.
I don't know that there is necessarily a full fix needed in this current PR, but:
- We should write this down somewhere, probably a TODO in the code and a Ruby issue, and
- We should add a test for catching that local being written to from a nested ISEQ; it will pass right now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's a bad guess but I kind of expect upper-local writes like this to be common but other get-my-caller-and-write-its-locals shenanigans to be more rare.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼 6e85878. Actually, the test fails right now because assert_compile() catches that Send doesn't compile. So I'm checking it in as skipped for now. Shopify#596
They're only used when level≠0. Same EP hopping logic as interpreter and YJIT. Change assert_compiles() to get ISeq by method name since the old code didn't support methods defined using define_method() which I need for the new test.
getlocal
andsetlocal
to HIR