HolyJit

HolyJit: Fire the IonCannon!

IonMonkey poster

This Presentation

  1. SpiderMonkey's JIT Problems.
  2. HolyJit Proposal.
  3. HolyJit Timeline.
  4. Demo & What To Expect Next.

SpiderMonkey's JIT Problems

Large

  • js/src/jit contains ~5% of Firefox C++ code.
  • Jit teams is 3 — 5 persons (4.3% under Selena Deckelmann, 1.6% under Dave Camp).

Complex

  • Targets an evolving language. (JavaScript)
  • Manually duplicate code written in C++.
  • Manually specialize based on type.
  • Manually assemble with a MacroAssembler.
  • ~14850 lines contains "masm" under js/src/.
  • js/src/jit: Bugs per lines = 14‰.

Incomplete

  • Baseline supports an optimized sub-set of the Interpreter.
  • Cache IR supports an optimized sub-set of the Interpreter / VM.
  • IonMonkey (MIR) supports an optimized sub-set of the Interpreter / VM / Builtins.
  • js/src/jit: 867 bugs have the verb "Add" in the subject (22.2% of bugs).

Insecure

  • MacroAssembler: Assembly code with holes.
  • SelfHosted: Random memory accesses in JS.
  • 570 crashes contains "js/src/jit/" (14.6% of bugs).
  • 208 security bug contains "js/src/jit/" (5.3% of bugs).
  • Crashes have between 1—143 comments (median: ~10).
  • Security issues have between 6—83 comments (median: 22).
  • ~13840 lines of self-hosted JavaScript code! (js/src/builtin/*.js)

Hard choices

  • Self-hosting: Choose between fast start-up (xor) fast steady runs.
  • Baseline: Hours of work for simple additions.
  • IonMonkey: Hours of work for simple additions.

If we continue the same way…

  • Lagging behind on JIT-ing new JavaScript features.
  • Same amount of work as the competition. (i-e a lot of efforts)

HolyJit Proposal

https://github.com/nbp/holyjit

1 year ago!

One of the thing I was interested in making such abstraction above our the MacroAssembler, was the ability to have completeness, and IC, and Inline code, from the Interpreter to Ion, with a single implementation.

Nicolas B. Pierron — 19 Oct 2016

Overview

General Purpose

  • Embeddable library.
  • Language independent.
  • Jit Rust code: At compile time & At run time.

Simple

  • Low-level IR. (WASM-like?)
  • Finite set of instructions. (increasing with hardware?)
  • Alias Set provided by the static compiler.

Code Annotation

  • Used to guide pre-compiled teiring.
  • Made with Rust Macro (no-op artifacts)
  • The Plugin is guided by these annotations.
  • Used for: guards, inline caches, unrolling loops, escape analysis, ignoring code, inlining, etc.

Similar Projects

  • RPython (PyPy)
  • GraalVM + Truffle

Differences

  • A single language is both statically/dynamically-compiled (self-hosting)
  • Rust is the future of Firefox (not Python / Java).

Opportunities

  • Both a method compiler, and a trace-compiler (for inline caches)
  • Better optimizing compiler design.
  • Use it as an AOT-compiler for Rust code. (maybe?)

More Security

  • Option to generate code in another process.

Method Compiler(s)

  • Define one entry point.
  • Unroll the Interpreter loop.
  • Scalar-replace & Recover the stack.

Trace Compiler

  • Generate Inline Caches.
  • Generate tracing code ahead-of-time.
  • Guard for annotated values.
  • Propagate constants in traces.
  • Pre-compile stubs ahead-of-time. (similar to Baseline)

Optimizing Compiler

… hand wave upcoming svg files …

Generate Code

  • Always use Cretonne.
  • Pre-compiled with fixed register allocation. (similar to Baseline)

HolyJit Timeline

Long Term

  • Rewrite the Interpreter and Builtins in Rust.
  • Use HolyJit to compile it.
  • Compete with IonMonkey & Baseline.

Mid Term

  • CSS selector matcher.
  • WebRender CPU backend.
  • RegExp Engine.
  • WASM optimizing compiler. (?)

Short Term

  • Requirements from Rust-compiler team.
  • Requirements from Build-system team.
  • Follow rustc closely.

Mid—Long Term Issue

  • Do we have a dynamic language except JavaScript?
  • Should we make a Servo-like JavaScript engine?
  • Should we contribute to another dynamic language …?… VM?

Demo

… Demo Time …

Array.push

$ git show ':/Bug 966743'

Array.push (before)

        fn array_push(args: &CallArgs) -> Result<JSValue, Error> {
          jit_inline_if!(args.len() == 1);
        
        }
      

Array.push (after)

        fn array_push(args: &CallArgs) -> Result<JSValue, Error> {
          jit_inline_if!(args.len() >= 1);
        
        }
      

Jit macros

  • jit_inline_if!(… cond …)
  • jit_guard!{… expr …}
  • jit_inline_cache!{… code …}
  • jit_unroll_loop!{… loop body …}
  • jit_constant!{… expr …}
  • jit_inline_type!{… expr …}
  • jit_skip!{… code … }

JSOP_ADD walkthrough

… Live annotation of SpiderMonkey's code …

Questions?

  1. Your turn to ask your questions.
  2. My turn to ask you questions.

Yes / No?