The FTL is integrated as an alternative backend for the DFG JIT but largely reuses existing DFG functionality. The FTL differs from the DFG as follows:
- Instead of generating machine code directly from the DFG IR, the DFG IR is lowered to LLVM IR and then the LLVM optimization pipeline and backend are invoked to generate machine code. That machine code is then managed by the JSC executable memory manager no differently than if it were generated by our own backends.
- Additional DFG phases are used. Running in FTL mode causes the DFG to lower to SSA even before lowering to LLVM IR. Additional optimizations like LICM are performed on the DFG-SSA IR.
The FTL JIT already supports key DFG concepts like OSR entry, OSR exit, and concurrent compilation.
Try it out
You can try out the FTL JIT on the Mac port by doing:
Tools/Scripts/build-jsc --ftl-jit --debug
Tools/Scripts/build-jsc --ftl-jit --release
Note that this requires either having binary drops of LLVM headers and static libraries, or having your own LLVM checkout.
Also note that building directly from Xcode is not supported at this time.
Building from binary drops
Building from your own LLVM checkout
The easiest way to build with your own LLVM checkout is to check out llvm into a directory called 'llvm' directly inside your checkout of WebKit. If you do this, build-jsc and friends will automatically configure and make this LLVM tree and pull the binaries into WebKit's build. LLVM's configure script is only run if we detect that you hadn't already run it. The default configuration parameters are kept in Tools/Scripts/configure-llvm.
There are two alternatives that give you varying degrees of control over how WebKit builds LLVM.
- You can put your LLVM checkout wherever you like and then make sure that the LLVM_SOURCE_PATH environment variable to tell WebKit's build system where the checkout is. WebKit's build system will still configure/make LLVM as necessary every time you build WebKit.
- You can build LLVM yourself and opt out of WebKit building it for you. The process for this is a bit convoluted, but it does work. After you build LLVM, use the Tools/Scripts/export-llvm-build script to create tarballs of LLVM's headers and libraries. Then use the LLVM_LIBRARY_PACKAGE and LLVM_INCLUDE_PACKAGE environment variables to tell us where you put those tarballs.
For further information, consult the Tools/Scripts/copy-webkitlibraries-to-product-directory script, which handles all of this magic.
The FTL JIT is runtime-disabled even when it is buildtime-enabled. Hence to run a program with the FTL JIT you also need the --useExperimentalFTL=true option, like:
DYLD_FRAMEWORK_PATH=WebKitBuild/Debug WebKitBuild/Debug/jsc --useExperimentalFTL=true <my JS program>
You can run the test suite including the FTL JIT by doing:
Looking at IR
Additional options allow for inspecting the IR that the FTL generates.
See if LLVM is being used to compile a function
DYLD_FRAMEWORK_PATH=WebKitBuild/Debug WebKitBuild/Debug/jsc --useExperimentalFTL=true --reportCompileTimes=true <my JS program>
Dump all LLVM IR
DYLD_FRAMEWORK_PATH=WebKitBuild/Debug WebKitBuild/Debug/jsc --useExperimentalFTL=true --dumpLLVMIR=true <my JS program>
Dump DFG IR and LLVM IR before and after LLVM optimization
DYLD_FRAMEWORK_PATH=WebKitBuild/Debug WebKitBuild/Debug/jsc --useExperimentalFTL=true --verboseCompilation=true <my JS program>
This will also tell if why some functions don't get FTL compiled. The FTL doesn't have full coverage over DFG IR yet. If JSC chooses not to use the FTL JIT for a code block, you will see a dump explaining why.
Dump all machine code
DYLD_FRAMEWORK_PATH=WebKitBuild/Debug WebKitBuild/Debug/jsc --useExperimentalFTL=true --showDFGDisassembly=true <my JS program>
This will also dump FTL disassembly, using the LLVM disassembler.