mcpField
J
jit-compilation

jit-compilation

github.com/mohitmishra786开发269306 次安装18 周前更新
代码仓库

关于 jit-compilation

面向实现即时编译的 Agent,涵盖 LLVM ORC/LLJIT、Cranelift 和 Rust dynasm,也介绍延迟编译、内联缓存及可执行内存安全。

主要功能

  1. 01LLVM ORC JIT v2 和 LLJIT 指引
  2. 02Cranelift JIT 配置
  3. 03使用跳板实现延迟编译
  4. 04内联缓存设计
  5. 05W^X 与 JIT 安全
  6. 06Rust dynasm x86 代码生成

适用场景

  1. 01为解释器添加 JIT 热路径
  2. 02首次调用时编译函数
  3. 03在 REPL 或游戏引擎中嵌入代码生成
  4. 04用 Rust 生成 x86 代码片段

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill jit-compilation

安装后在 Claude Code 中输入/jit-compilation确认已加载。

详细介绍

JIT 编译

用途

指导 Agent 使用即时编译:LLVM ORC JIT v2(ExecutionSession、IRLayer、ObjectLayer)、适用于简单场景的 LLJIT、Cranelift JIT、用于动态分发的内联缓存、用于延迟编译的跳板、安全注意事项(W^X、代码签名),以及用于 x86 代码生成的 Rust dynasm。

适用场景

  • 构建带有 JIT 热路径的解释器
  • 实现首次调用时的函数延迟编译
  • 在 REPL 或游戏引擎中嵌入动态代码生成
  • 无需编写完整链接器即可对代码生成进行原型设计
  • 为多态调用点创建内联缓存
  • 使用 Rust 的 dynasm 生成 x86 机器码

工作流

1. JIT 架构概览
Source/AST/Bytecode
    → IR (LLVM IR or Cranelift CLIF)
    → Object file (in memory)
    → Runtime linker (RTDyldObjectLinkingLayer)
    → Executable code in R+X memory
    → Function pointer call
2. LLJIT — 最简单的 LLVM JIT
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"

using namespace llvm;
using namespace llvm::orc;

int main() {
    auto JIT = cantFail(LLJITBuilder().create());

    LLVMContext Context;
    auto M = std::make_unique<Module>("jit", Context);
    IRBuilder<> Builder(Context);

    // int add(int a, int b) { return a + b; }
    Function *AddFn = Function::Create(
        FunctionType::get(Builder.getInt32Ty(),
                          {Builder.getInt32Ty(), Builder.getInt32Ty()}, false),
        Function::ExternalLinkage, "add", M.get());

    BasicBlock *BB = BasicBlock::Create(Context, "entry", AddFn);
    Builder.SetInsertPoint(BB);
    auto Args = AddFn->arg_begin();
    Value *Sum = Builder.CreateAdd(Args, Args + 1);
    Builder.CreateRet(Sum);

    cantFail(JIT->addIRModule(ThreadSafeModule(std::move(M), std::make_unique<LLVMContext>())));

    auto AddSym = JIT->lookup("add");
    auto *AddPtr = (int (*)(int, int))AddSym->getValue();
    int result = AddPtr(3, 4);  // 7
    return 0;
}
clang++ -std=c++17 jit.cpp $(llvm-config --cxxflags --ldflags --libs core orcjit native) -o jit
3. ORC JIT v2 层
ExecutionSession ES;
auto &MainJD = ES.createBareJITDylib("main");

RTDyldObjectLinkingLayer ObjectLayer(
    ES, []() { return std::make_unique<SectionMemoryManager>(); });

IRCompileLayer CompileLayer(
    ES, ObjectLayer, std::make_unique<TargetMachineBuilder>());

// Add IR module to JITDylib
ThreadSafeModule TSM = ...;
CompileLayer.add(MainJD, std::move(TSM));

// Resolve symbol
auto Sym = ES.lookup({&MainJD}, "my_func");

各层:

  • IRLayer — 将 LLVM IR 编译为目标文件
  • ObjectLayer — 链接可重定位目标文件
  • ExecutionSession — 符号查找和 JITDylib 管理
4. 使用跳板进行延迟编译
First call → trampoline → compile function → patch trampoline → direct call
// Simplified lazy compile on first invocation
void *LazyCompile(const std::string &Name) {
    if (!Compiled.count(Name)) {
        auto Fn = CompileFromAST(Name);
        Compiled[Name] = Fn;
        // Patch call site or update function pointer table
    }
    return Compiled[Name];
}

ORC 支持通过 LazyCallThroughManager 实现延迟再导出和延迟编译。

5. 内联缓存
// Concept: monomorphic call site caches resolved target
// Pseudocode for dynamic language
function call_site(obj, method, args) {
    if (obj.class_id === cache.class_id) {
        return cache.fn_ptr(args);  // fast path
    }
    cache.class_id = obj.class_id;
    cache.fn_ptr = resolve_method(obj, method);
    return cache.fn_ptr(args);
}

JIT 会为每种缓存类型生成专用代码;缓存未命中时进行去优化。

6. Cranelift JIT
use cranelift::prelude::*;
use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{Linkage, Module};

let isa = cranelift_native::builder().finish(settings::Flags::new(settings::builder()))?;
let jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
let mut module = JITModule::new(jit_builder);

let mut ctx = module.make_context();
ctx.func = Function::with_name_signature(
    module.declare_function("add", Linkage::Export, &sig)?,
    sig,
);
// ... build IR in ctx.func ...
module.define_function(func_id, &mut ctx)?;
module.finalize_definitions()?;
let code = module.get_finalized_function(func_id);
let add_fn: fn(i32, i32) -> i32 = unsafe { std::mem::transmute(code) };

Cranelift 的编译速度比 LLVM 更快,适合可嵌入式 JIT。

7. 安全 — W^X 策略
W^X (Write XOR Execute)
├── Memory page is writable OR executable, never both
├── JIT: allocate RW → write code → mprotect(RX)
└── macOS hardened runtime requires signed JIT pages
#include <sys/mman.h>

void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE,
                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// write machine code to mem
mprotect(mem, size, PROT_READ | PROT_EXEC);

Linux:在 Apple 平台上使用 MAP_JIT;在经过强化的系统上使用 sealed memfd。

8. Rust dynasm(x86)
use dynasm::dynasm;
use dynasmrt::{Assembler, ExecutableBuffer};

let mut asm = Assembler::new().unwrap();
dynasm!(asm
    ; .arch x86_64
    ; add:
    ; add eax, ecx
    ; ret
);
let buf = asm.finalize().unwrap();
let add_fn: fn(i32, i32) -> i32 = unsafe { std::mem::transmute(buf.ptr(0)) };

适用于不依赖 LLVM 的轻量级汇编代码片段。

9. 决策树
JIT backend choice?
├── Need LLVM optimizations → ORC JIT / LLJIT
├── Fast compile, embeddable → Cranelift
├── Tiny asm snippets → dynasm
└── ML workloads → MLIR → ORC pipeline

常见问题

症状原因修复方法
查找时找不到符号名称修饰或未导出使用 C 链接;LLVMExternalLinkage
调用 JIT 代码时发生段错误ABI 不匹配匹配调用约定和类型
W^X mmap 失败SELinux/grsecurity使用 MAP_JIT;检查 dmesg
重新编译后代码仍然过时函数指针指向旧代码使缓存失效;使用跳板
LLVM JIT 编译缓慢JIT 中使用了 -O2JIT 使用 -O0;仅优化热点路径
Cranelift 验证错误CLIF 无效启用 cranelift_codegen::verify_function

相关技能

  • skills/compiler-internals/llvm-passes — 在 JIT 前进行优化
  • skills/compiler-internals/compiler-frontend — 将 AST 转为 JIT 输入的 IR
  • skills/compiler-internals/mlir — 将 MLIR 降低为用于 JIT 的 LLVM
  • skills/compilers/llvm — LLVM IR 基础
  • skills/low-level-programming/interpreters — 使用 JIT 的字节码解释器
  • skills/low-level-programming/assembly-x86 — 手写汇编的背景知识

评论

支持 Markdown