Skip to content

Instantly share code, notes, and snippets.

@JustinMeimar
Created April 30, 2026 18:47
Show Gist options
  • Select an option

  • Save JustinMeimar/c3423623b46a331dfbda97cddaf2dfcd to your computer and use it in GitHub Desktop.

Select an option

Save JustinMeimar/c3423623b46a331dfbda97cddaf2dfcd to your computer and use it in GitHub Desktop.
problem with TLS used in AOT code when in browser and two explored solutions

problem:

We use TLS to load the &AOTIndirectionTable (TLS -> JSContext -> JSRuntime -> JitRuntime -> AOTIndirectionTable) into a BaselineFrame field, allowing AOT indirections to go through the FramePointer. TLS doesn't work in AOT code since the offset into the storage is non-deterministic in a dynamic library. If TLS causes an issue, the obvious solution is to take it out. First we need to characterize where TLS is used.

    1. In emitInitFrameFields both for baseline Interp and Compile
    1. In emit_Resume, since resuming a generator creates a new baseline frame. The TLS can be avoided here by copying the &AOTIndirectionTable from the parent BaselineFrame. There should always be a parent frame for a resume op I think...

solution attempt-1:

  • Using a movWithPatch in place of TLS loads. This emits a hole in the locations above which can be patched at load time with &AOTIndirectionTable. The problem is that the patch is an address. AOT blnterp code is immutable .text shared between workers, each with their own JitRuntime. The profiler/debugger patching isn't affected by this since the patches are not addresses, but rather instructions like nop. N workers patching their own address for the table simply doesn't work.

solution attempt-2:

  • If we can write &AOTIndirectionTable into a pinned register in all entry points, then our indirections are simple inside baseline (and faster). The difficulty is in preventing the register from being clobbered. AFAICT the only candidate register is r13 on x64.

    • Mirrored saveInterpreterPC and resotreInterpreterPC (r12 on x64) allowed most tests to pass.

    • r13 used as a scratch register in WASM stubs, the GenerateImportJitExit transition point from WASM to JS. This is another place (like EnterJit trampoline for C++ -> JIT), where we need to ensure that r13 has the AOTIndirectionTable setup. Solved this for now by switching ABINonVolatileReg to rbx on x64, which gives more assurance when using r13.

    • This strategy is passing shell tests as of today, so looks hopeful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment