You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When we generate JITted code, the JIT frame has it's own stack. We need to start thinking about what the alignment requirements are of storing things to that stack.
I think there are two ways an object can hit the JIT stack:
via a spill of a local variable (determined by register allocation)
via an explicit stack allocation opcode (if we introduce one -- I think we will need one). For example LLVM has the alloca instruction.
For the former I think that the only requirements are those of the underlying CPU architecture. In other words, no object that is word-sized [0] or less should straddle a word boundary. Why? Because some CPUs will emit slower code to handle a straddle, some CPUs will actually fault (sparc64/arm I think).
For explicit stack allocations the AOT binary may have been code-genned with certain alignment requirements baked-in, and pointers may be shared across AOT and JIT code (via the shadow stack). For those cases I think we have no choice but to align as LLVM aligned. This would entail carrying the alignment value from the LLVM's alloca into our own IR instruction and when we perform the allocation, ensure (like the dude) that we abide.
[One spanner in the works is that LLVM loads and stores can take an alignment parameter too, but it's rare. For that I suggest we start by assert()ing it can't happen during lowering to our IR]
Does this all sound legit?
I don't actually plan to get alignment 100% correct right now, since we are in sprint mode, but I want to at least have said that I have thought about it :)
Right now we have no explicit stack allocations, and spills are aligned to the size of their allocation. The latter is not strictly correct and often wasteful, but will probably work for now at least on x86_64. A less dodgy scheme for spills is to align to the highest alignment value of the object's constituent "fields" (or sub-objects, whatever you want to call them).
The text was updated successfully, but these errors were encountered:
I am increasingly worried that we haven't thought about alignment at all, anywhere in any part of yk, and we're gradually embedding more assumptions about alignment that are not just incorrect but also unnoticed and hard to track down later.
Rather than start at the end (the codegen), what would be better is to start at the start: ykllvm and yksmp. Can we get alignment data into those parts? If we can, we'll relatively naturally be able to thread it throughout the system.
@vext01 Do you have any sense of whether/how ykllvm and yksmp give us alignment information?
As discussed offline, our IR works under the assumption that all objects are alignment-safe and the serialiser will reject any load/store that could straddle an alignment boundary.
However we'd like to make alignment more explicit and encode the alignment into our IRs and let the code generator decide whether it wants to handle (or not) misaligned loads/stores.
(Note to self: also encode alignment into allocas, so the codegen can allocate appropriately for (e.g.) implicit alignment requirements external to IRs)
When we generate JITted code, the JIT frame has it's own stack. We need to start thinking about what the alignment requirements are of storing things to that stack.
I think there are two ways an object can hit the JIT stack:
alloca
instruction.For the former I think that the only requirements are those of the underlying CPU architecture. In other words, no object that is word-sized [0] or less should straddle a word boundary. Why? Because some CPUs will emit slower code to handle a straddle, some CPUs will actually fault (sparc64/arm I think).
For explicit stack allocations the AOT binary may have been code-genned with certain alignment requirements baked-in, and pointers may be shared across AOT and JIT code (via the shadow stack). For those cases I think we have no choice but to align as LLVM aligned. This would entail carrying the alignment value from the LLVM's
alloca
into our own IR instruction and when we perform the allocation, ensure (like the dude) that we abide.[One spanner in the works is that LLVM loads and stores can take an alignment parameter too, but it's rare. For that I suggest we start by assert()ing it can't happen during lowering to our IR]
Does this all sound legit?
I don't actually plan to get alignment 100% correct right now, since we are in sprint mode, but I want to at least have said that I have thought about it :)
Right now we have no explicit stack allocations, and spills are aligned to the size of their allocation. The latter is not strictly correct and often wasteful, but will probably work for now at least on x86_64. A less dodgy scheme for spills is to align to the highest alignment value of the object's constituent "fields" (or sub-objects, whatever you want to call them).
The text was updated successfully, but these errors were encountered: