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

Enable stackmap support for tracking multiple locations. #57

Merged
merged 2 commits into from
Feb 24, 2023

Conversation

ptersilie
Copy link

Currently, stackmaps can only track one location per live variable, e.g. from the view of the stackmap a live variable is either in a register or on the stack. When deoptimising into machine code, this isn't sufficient since spilling will often create copies of a variable in multiple locations. This PR extends stackmaps to track an additional location for live variables in registers, i.e. in additional to the register location there can be another register location or a stack offset.

Note, that this makes some assumptions that may not hold in the general case, but will get us going on our way to fully trace Lua. We might have come back to revisit this code, if issues arise later on.

@ptersilie
Copy link
Author

Think that's all comments addressed.

@ltratt
Copy link

ltratt commented Feb 22, 2023

Please squash.

@ptersilie
Copy link
Author

Squashed.

@ltratt
Copy link

ltratt commented Feb 23, 2023

bors r+

@bors
Copy link

bors bot commented Feb 23, 2023

Build failed:

@ptersilie
Copy link
Author

19e48c2 should take care of those tests. Requires squashing.

@ltratt
Copy link

ltratt commented Feb 23, 2023

Please squash.

Stackmaps only track one location per live variable, e.g. in a register,
on the stack, etc. However, when deoptimising to native stack frames
values may exist in multiple locations, e.g. in a register as well as on
the stack or in two registers.

The main reason for this, at least from observation, are spills before
function calls. For example, if a value is held in $rdi and that
register needs to be freed up to execute a call, the register allocator
may spill it to a register or onto the stack. After the call is done the
value is reloaded. A simple optimisation is to cache the spills so the
value can be reloaded throughout a function without having to respill it
every time. Depending on where the stackmap call is located we can only
see the restored register but not the spill. During deoptimisation we
then only populate the tracked register with the right value. When the
program then decides to restore the register again (e.g. because it has
executed another call) loading it from the stack won't recover the value
since we haven't pushed it during optimisation.

This commit adds an analysis to the compiler chain that attempts to find
additional locations for live variables and encode them in stackmaps. It
does so but traversing the control flow of a function and creating a
mapping on any register moves, stack stores or reloads. For simplicity
(and so we don't need to change the stackmap format) we assume that only
one such additional location may exist (which may very well turn out to
be wrong in the future).

These changes enable us to run much further in some of the lua tests,
though there are still some bugs to be fixed.
Since the JIT compiler can inline indirect calls, we need to emit
stackmaps for them too. Since we can't tell if an indirect call is an
intrisnic (which doesn't need stackmaps) this will inevitably create
some unneeded stackmap calls. But since they'll never be used, all they
cost is space in the binary.
@ptersilie
Copy link
Author

Squashed.

@ltratt
Copy link

ltratt commented Feb 24, 2023

bors r+

@bors
Copy link

bors bot commented Feb 24, 2023

Build succeeded:

@bors bors bot merged commit 2acbfa1 into ykjit:main Feb 24, 2023
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

Successfully merging this pull request may close these issues.

3 participants