rcowsill.github.io

github.com/rcowsill

Slow Entry Trampoline?

This week I’ve been using Firefox Profiler on a site I’m building. While looking at the stack chart of a WebAssembly function, I noticed this:

Stack Chart showing a WebAssembly function called via "slow entry trampoline"

Between my JavaScript and WebAssembly functions there’s a “slow entry trampoline”. That raised two questions:

Q1: What is a “slow entry trampoline”?

This took a bit of digging to find out. A web search got no hits for that phrase, and it wasn’t mentioned in the Firefox Profiler documentation.

In the end I found the answer in the Firefox source code:

Searchfox results page for the words "slow entry trampoline"

The second result lead to WasmFrameIter.cpp:

switch (codeRange_->kind()) {
  [...]
  case CodeRange::InterpEntry:
    return "slow entry trampoline (in wasm)";
  case CodeRange::JitEntry:
    return "fast entry trampoline (in wasm)";

CodeRange is defined in WasmCodegenTypes.h:

class CodeRange {
 public:
  enum Kind {
    [...]
    InterpEntry,       // calls into wasm from C++
    JitEntry,          // calls into wasm from jit code

So a “slow entry trampoline” is just the code used by the JavaScript interpreter to call a WebAssembly function. The interpreter is written in C++, which is why that’s mentioned in the comment.

For more detail on how calls between JavaScript and WebAssembly are handled, see this Mozilla Hacks post.

Q2: Can I make that a “fast entry trampoline” somehow?

Probably not. The entry trampoline is selected based on whether the calling JavaScript code is interpreted or JIT compiled. That’s mostly in the hands of the JavaScript engine.

Conclusion

In my case the calling code runs infrequently, and the WebAssembly function does a significant amount of work before returning. That means the JavaScript engine is unlikely to JIT the calling code.

The same situation is likely to arise anywhere WebAssembly is used to optimise a hot path.

In a way, I think seeing the slow trampoline on the stack indicates that all’s well. If the calling code runs infrequently enough to remain interpreted, the total call cost is probably insignificant.