Lesson 6 of 7

Code Generation, Linking & JITs

This lesson covers the final stages: turning IR into real instructions, linking separate files into one executable, and how JIT do all of this while a program runs.

Codegen makes two hard choices. Instruction selection: which of the CPU's instructions implement each IR operation (x86 can often fold load-add-store into one instruction; ARM can't). Register allocation: the IR pretends registers are infinite, hardware has ~16 — graph coloring assigns the busiest values to registers and 'spills' the rest to . Register pressure is a real performance force: too many live means spills, means memory traffic.

Bash
# Separate compilation + linking — how big projects build:
gcc -c utils.c        # -> utils.o   (machine code, but
gcc -c main.c         # -> main.o     unresolved references)
gcc main.o utils.o -o app     # linker joins them

# main.o contains 'call helper' with a BLANK address and
# a note: "patch this when you find 'helper'". The linker
# resolves every such note across all .o files + libraries.

# 'undefined reference to helper' = linker found no
#   definition anywhere (forgot a file or a library flag).
# 'duplicate symbol' = found two.

nm utils.o            # see a file's symbols: T=defined, U=needed

Static linking copies code into your (bigger, -contained — Go's default). Dynamic linking loads shared libraries (.so/.dll) at startup, so all programs share one libc in memory and library fixes arrive without recompiling — at the cost of 'DLL hell' version mismatches. Every deployment headache about glibc versions traces here.

Text
JIT compilation — V8 running your JavaScript:

 1. Parse to bytecode, start interpreting immediately
 2. Profile while running: which functions are hot?
    what types actually flow through them?
 3. Hot function -> compile to machine code SPECIALIZED
    to the observed types ("x is always a small int")
 4. Guard checks protect the assumption; if a string
    shows up one day -> DEOPTIMIZE: throw away the
    fast code, fall back, maybe recompile

Why JS engines love consistent types — and why that
advice exists: monomorphic code stays compiled;
type-shifting code bounces between tiers.

The full pipeline, running in milliseconds,
while your page loads.
Finished reading?Mark it done to track your progress.

Tip: use the ← and → keys to move between lessons.