Crate sjlj2

Source
Expand description

§Safer1, cheaper and more ergonomic setjmp/longjmp in assembly.

  • Ergonomic and safer Rusty API for typical usages. Closure API instead of multiple-return.

    Multiple-return functions are undefined behaviors due to fatal interaction with optimizer. This crate does not suffer from the misoptimization (covered in tests/smoke.rs). If you find any misoptimization in practice, please open an issue.

    See long_jump for details.

  • Single-use jump checkpoint.

    No jump-after-jump disaster. No coroutine-at-home.

  • Minimal memory and performance footprint.

    Single usize JumpPoint. Let optimizer save only necessary states rather than bulk saving all callee-saved registers. Inline-able long_jump.

    On a modern x86_64 CPU:

    • 2.7ns catch_long_jump without long_jump.
    • 3.4ns catch_long_jump+long_jump. ~416x faster than catch_unwind-panic_any.
  • No libc or C compiler dependency.

    The low-level implementation is written in inline assembly.

  • no_std support.

    By default, this crate is #![no_std] and does not use alloc either. It is suitable for embedded environment.

use std::ops::ControlFlow;
use sjlj2::catch_long_jump;

let mut a = 42;
// Execute with a jump checkpoint. Both closures can return a value.
let ret = catch_long_jump(|jump_point| {
    a = 13;
    // Jump back to the alternative path with an arbitrary `usize` payload.
    // SAFETY: All frames between `catch_long_jump` and the current are POFs.
    unsafe {
        jump_point.long_jump(99);
    }
});
assert_eq!(ret, ControlFlow::Break(99));

§Cargo features

  • unwind: Enables unwinding across catch_long_jump boundary, by catching and resuming the panic payload. This feature requires std.

No feature is enabled by default.

§Supported architectures

  • x86 (i686)
  • x86_64
  • riscv64
  • riscv32, with or without E-extension
  • aarch64 (ARM v8)
  • arm

§Similar crates

  • setjmp

    • Generates from C thus needs a correctly-setup C compiler to build.
    • Unknown performance because it fails to build for me. (Poor compatibility?)
    • Suffers from misoptimization.
  • sjlj

    • Only x86_64 is supported.
    • Suffers from misoptimization due to multi-return.
    • Slower long_jump because of more register restoring.

  1. long_jump is still unsafe and is technically UB, though. See more about safety in long_jump

Structs§

JumpPoint
A jump checkpoint that you can go back to at any time.

Functions§

catch_long_jump
Invokes a closure with a jump checkpoint.
long_jump
Long jump to a checkpoint, force unwinding the stack and return an arbitrary data to an early catch_long_jump specified by point.