JIT Compilation

Joule supports just-in-time compilation for interactive development. Instead of producing an executable file, the compiler compiles your code in memory and runs it immediately.

Quick Start

# JIT-compile and run
joulec --jit program.joule

# Watch mode: re-compile on file changes
joulec --watch program.joule

Requirements

JIT mode requires the jit feature flag, which enables the Cranelift JIT backend:

# Build joulec with JIT support
cargo build --release -p joulec --features jit

The feature chain is: jit -> cranelift -> joule-codegen-cranelift + joule-codegen + notify.

How It Works

JIT Mode (--jit)

  1. Source code is parsed, type-checked, and lowered to MIR (the same pipeline as normal compilation)
  2. MIR is translated to Cranelift IR
  3. Cranelift compiles the IR to native machine code in memory
  4. The main() function is called directly via a function pointer
  5. The program runs and exits

No intermediate files are produced. No C compiler is invoked. Compilation and execution happen in a single process.

Watch Mode (--watch)

Watch mode extends JIT with file monitoring:

  1. The source file is JIT-compiled and run (same as --jit)
  2. The notify crate monitors the source file for changes
  3. When the file is saved, a fresh JIT module is created and the program re-runs
  4. A 50ms debounce prevents multiple re-runs from editor save-rename sequences

Each watch cycle creates a fresh JITModule because Cranelift's JIT module cannot redefine functions. This ensures clean state on every re-run.

Architecture

FunctionTranslator

The FunctionTranslator<'a, M: Module> is generic over the module type:

Module TypeModeOutput
ObjectModuleAOT compilationObject file (.o)
JITModuleJIT compilationIn-memory executable code

This means the same translation logic handles both AOT and JIT -- no code duplication.

Runtime Symbols

JIT mode provides runtime symbols that replace the C runtime's functions:

SymbolPurpose
joule_jit_printlnPrint a string with newline
joule_jit_printPrint a string without newline
joule_jit_panicPanic with a message
mallocMemory allocation (libc)
freeMemory deallocation (libc)
memcpyMemory copy (libc)

These symbols are registered with the JITModule before compilation so that generated code can call them.

PIC Mode

JIT compilation uses position-independent code (PIC) = false, since the code runs in a known memory location. AOT compilation uses PIC = true for shared library compatibility.

Energy Tracking

JIT mode includes full energy tracking. Energy consumed during execution is measured and reported:

$ joulec --jit program.joule
Hello from JIT!
Energy consumed: 0.000123 J

Energy budgets declared with #[energy_budget] are checked at compile time, before JIT execution begins. If a budget is violated, compilation fails and the program does not run.

Limitations

  • No persistent output: JIT mode does not produce an executable file. For deployment, use the C backend or AOT Cranelift compilation.
  • Single-file: JIT mode currently compiles a single source file. Multi-file projects should use mod declarations within the entry file.
  • Feature gate: JIT support is behind --features jit to keep the default binary small. The notify dependency is only pulled in when JIT is enabled.

Use Cases

Rapid Prototyping

JIT mode eliminates the compile-link-run cycle:

# Edit, save, see results instantly
joulec --watch prototype.joule

Energy Experimentation

Try different algorithms and immediately see their energy impact:

// Try bubble sort
#[energy_budget(max_joules = 0.001)]
fn sort_experiment(data: Vec<i32>) -> Vec<i32> {
    bubble_sort(data)
}
joulec --jit experiment.joule
# Change to quicksort, save, see new energy reading

Interactive Testing

Run tests without a full build:

joulec --jit --test tests.joule

Comparison with Other Modes

ModeCommandSpeedOutputUse Case
JIT--jitFastestNone (runs in memory)Development
Watch--watchFast (re-runs on save)NoneInteractive development
C Backend--emit cModerate.c fileDeployment, bootstrap
Cranelift AOT(default)FastBinaryDevelopment builds
LLVM--features llvmSlowOptimized binaryRelease builds