Closed Bug 1584370 Opened 5 years ago Closed 5 years ago

Need info about safe assumptions for Cranelift's register use

Categories

(Core :: JavaScript: WebAssembly, task)

task
Not set
normal

Tracking

()

RESOLVED MOVED

People

(Reporter: shravanrn, Unassigned)

References

(Blocks 2 open bugs)

Details

This bug is in the context of use of Cranelift to generate wasm sandboxed libraries for use in Firefox - i.e. this is a non web embedding. Full details available here https://bugzilla.mozilla.org/show_bug.cgi?id=1562797

We are using lucet as our wasm compiler which uses Cranelift under the covers. For performance reasons, we need to optimize transitions between native code and wasm sandboxed code beyond what lucet provides out of the box. Key to this is generating efficient trampoline functions that minimize overhead.

To this end we have rewritten trampolines that make a few assumptions based on " properties derivable from the WASM spec about register and stack use of a WASM compiler". These assumptions reduces overhead when using a sandboxed version of libGraphite by several 100's of percent.

Since this is something indirectly implied from the WASM spec, I am hoping that Cranelift can guarantee these and wanted to confirm if these are OK.

There are 3 assumptions - one about stacks, and two about register use

  1. Assembly functions generated by Cranelift WASM never underflows the stack
    • This is guaranteed from the WASM spec due to the fact that WASM functions are proper stack machines
    • This would allow us to use the same stack for the application and wasm module
    • However, our reliance on this depends on how bug-free we think Cranelift's conversion from the WASM stack machine
  2. Assembly functions generated by Cranelift never reads an uninitialized register
    • This is an outcome of all function calls to WASM and within WASM (including indirect jumps) being typesafe.
    • This means there should never be code generated that reads from a scratch register prior to writing to it.
    • This also means there should never be code generate for a function that takes 2 parameters, that attempts to read a value from the register that would hold a third parameter (if it had existed)
    • This allows us to avoid clearing scratch and unused parameter registers during WASM function invocation.
  3. Assembly functions generated by Cranelift always restore callee save registers
    • Like point 2, this is an outcome of all functions being typesafe combined with the fact that WASM is a stack machine, which cannot manipulate the stack in a way that affects register spills.
    • This means that there should no path through the function that would result in a callee save register not being restored
    • This allows us to avoid explicitly restoring registers on the way out

It strikes me that it may be more fruitful to have this discussion in the cranelift repository, https://github.com/CraneStation/cranelift.

I'm not sure how much we can say that the structure of Wasm bytecode leads to these properties being upheld. Take (2) for example. It is true that wasm is typesafe and that all locations start out initialized. But it does not follow that the generated code never reads an uninitialized register -- that depends on code generation strategies. It probably follows from typesafe-ness that the value of an uninitialized register is not used in a semantics-affecting way, but that is a slightly weaker property than you propose, though it has the effect that you're after, I expect.

Cranelift is subject to restrictions like the ones you propose from having to fit into SpiderMonkey and Firefox, however. Both (1) and the slightly weakened version of (2) I believe to be the case. As for (3), it is true at points when the callee-save registers are observable, that is, it is possible that eg trap handling can violate this property while a trap is being unwound, but the property will have been reestablished once the system reaches a state where it is possible to look at the registers, eg, at the boundary where control leaves compiled wasm code and returns into embedder code.

I should say, whether these properties hold may be ABI-dependent. As you know, Cranelift has support for multiple ABIs; the Firefox embedding uses the "baldrdash" ABI which guarantees the properties above. The other ABIs, System-V and Fastcall, may also guarantee them, but I don't know this for a fact.

It strikes me that it may be more fruitful to have this discussion in the cranelift repository, https://github.com/CraneStation/cranelift.

Gotcha! Opened bug on cranelift github and following up there

Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → MOVED
You need to log in before you can comment on or make changes to this bug.