-
Notifications
You must be signed in to change notification settings - Fork 5.4k
ZJIT: Implement concatstrings
#13789
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
base: master
Are you sure you want to change the base?
Conversation
// Save PC since the call allocates and can raise | ||
gen_save_pc(asm, state); | ||
|
||
// We've moved the SP, so the array is at SP or one element above |
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.
I was working on a branch for toregexp, which looks quite similar to this: https://github.com/ruby/ruby/compare/master...composerinteralia:ruby:zjit-toregexp?expand=1
I managed to avoid this conditional for where the array is located by growing the stack first, then putting the strings onto the stack relative to the new SP. That way the extra space for alignment ends up after the array instead of before it. Edit: Oops, ignore that. I had missed your comment about writing before moving SP since the source might be from the stack.
I was also playing around with a cpush_vec
, since I knew we'd need something like this for concatstring as well (and maybe some others). Not sure about it yet though.
(Sharing just in case it's helpful—I'll plan to update my toregexp
branch before opening a PR to match whatever you do here).
let dest = Opnd::mem(64, NATIVE_STACK_PTR, i32::try_from(strings.len() - i).ok()? * -SIZEOF_VALUE_I32); | ||
asm.mov(dest, jit.get_opnd(*string)?); | ||
} | ||
// Write, then move the SP, since the source might be from the stack |
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.
@k0kubun Actually, are all changes to SP unsafe because the backend will auto spill stuff around ccall based on a fixed offset from native SP? In other words, do we have to inform the backend about any changes to native SP if it does auto spill?
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.
are all changes to SP unsafe because the backend will auto spill stuff around ccall based on a fixed offset from native SP?
Are you saying giving (native) SP-based memory operands to ccall is unsafe because ccall may also bump the native SP to spill live registers before moving these memory operands into C argument registers? Is my understanding correct?
do we have to inform the backend about any changes to native SP if it does auto spill?
I guess we could maintain c_sp_offset
(or native_sp_offset
) in Assembler
and let the split pass adjust all memory operands based on native SP in its operand iterator loop. It might solve #13802 (comment) as well.
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.
Are you saying giving (native) SP-based memory operands to ccall is unsafe because ccall may also bump the native SP to spill live registers before moving these memory operands into C argument registers? Is my understanding correct?
Yeah, sounds like a possible failure mode. I see that spilling is not implemented for now 1. I was picturing a fixed-size frame for all auto generated spills, where there is a pre-determined offset for each VReg
at each spill site. It would just write to say, [SP, -0x20]
for some VReg
. If we change SP from underneath that code, it would clobber. Also, in case a spilled VReg
is passed as an argument and it auto-reloads it to a register, SP being different would have it read the wrong value.
I guess we could maintain c_sp_offset (or native_sp_offset) in Assembler and let the split pass adjust all memory operands based on native SP in its operand iterator loop. It might solve #13802 (comment) as well.
Something like that should work. These references are based on the native frame pointer, conventionally rbp
on x86, and because we don't keep a base pointer explicitly and SP can change, there is a moving offset to get the frame base from SP.
Footnotes
-
Or is this line outdated?
debug!("spilling VReg is not implemented yet, can't evacuate C_RET_REG on CCall");
↩
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.
Or is this line outdated?
We bail out on that now, so it doesn't panic anymore but it's still not implemented yet.
Keeping the same name makes re-exporting more concise.
Quite tricky to use the native stack to pass a C `VALUE[]`.
concatstrings
Quite tricky to use the native stack to pass a C
VALUE[]
.