Skip to content

rebar 0.6.0

Choose a tag to compare

@OverlordDev OverlordDev released this 05 Nov 19:18
· 37 commits to main since this release

Runs arm64 macOS programs on Intel/AMD (x86_64) Macs. A user-mode dynamic binary translator (interpreter + x86-64 JIT + Mach-O loader/bridge to the host's system libraries).

New in 0.6.0

Games and large apps

  • Cyberpunk 2077 (the Mac build, arm64) runs and is playable: 17–31 frames/s while driving and walking at 1920×1080 with low textures (the built-in benchmark averages 12) on a Ryzen 7 5800H + RTX 3070 Laptop with a third-party Metal driver for NVIDIA GeForce cards. Measured on that one machine only; frame generation does not work yet (the driver rejects a texture copy), MetalFX upscaling can show lighting artifacts indoors.
  • Steam (arm64) windows and its CEF helper processes start; Godot and Zed run.
  • objc_msgSend fast path: a plain send to a host method no longer takes the bridge lock three times. Sixteen threads encoding Metal commands used to queue on it: 8–12 → 17–31 frames/s in Cyberpunk 2077.
  • The JIT arena is 1920 MB (was 768 MB). A game whose translated code fills the arena used to run the rest in the interpreter, with every thread waiting for the translator lock: 3–4 s of translator time per second, now milliseconds. This is what made driving and loading new map areas stutter.
  • Float structures passed by value through objc_msgSend (setPosition:) no longer end the process; _vsyslog takes a va_list the right way.
  • REBAR_HUD=1 (a switch in the launcher's app settings): Apple's Metal performance HUD (frames/s, frame time, GPU time, memory) over the program's Metal windows.

Speed

  • Translation cache in ~/Library/Caches/rebar/jit: the start addresses of translated blocks and a snapshot of the translated code are saved and mapped back at the next start (REBAR_JIT_CACHE=0 turns it off, REBAR_JIT_CACHE_MAX_MB limits its size).
  • JIT templates for the AdvSIMD forms that went through helpers (widening add/sub/abd/multiply, halving adds, shifts with rounding and accumulation, MUL/MLA/MLS by element, FABD, rounding float↔int conversions): 282 of 361 probed forms were helpers, 68 are. rebar --jit-coverage reports it per encoding.
  • libm functions are leaf calls in translated code; a vector register cache; fewer store-forwarding stalls.

Instructions (checked against a C model, with and without the JIT)

  • BC.cond, CSSC, CPA, CASP (was decoded as STXP), LSE128, THE/RCW, LRCPC2/3, MOPS, MTE arithmetic and stores, RETAASPPC/RETABSPPC
  • SQSHL/UQSHL/SQRSHL/UQRSHL by register, SQDMLAL/SQDMLSL/SQDMULL, USQADD/SUQADD, URECPE/URSQRTE, FRECPX

Fixes

  • fork(): the child resets the locks the forking thread held (Steam's helper deadlocked at its first call into guest code).
  • A process started with SIGUSR2 blocked (the child of a guest's fork+exec) no longer dies at start.

Diagnostics: REBAR_PROFILE_THREADS=1 (a table per thread with REBAR_PROFILE), REBAR_JITTIME=1, REBAR_SLOW_STUB=<ms> names the Objective-C message, --probe-insns.

Also working (from earlier releases)

  • Go, Rust (rustc), CPython 3.13, Java, Node.js, Deno, Ruby, PHP, Erlang, GHC, OCaml, gcc; libc++ (C++20)
  • Frameworks: Accelerate, Vision, CoreML, CoreText, PDFKit, SceneKit, SpriteKit, ImageIO, AVFoundation, CoreImage, MetalPerformanceShaders, SwiftUI (ImageRenderer, Charts), XPC, dispatch, KVO
  • Swift Concurrency, key paths, SwiftUI, Swift Charts; Java HotSpot, .NET CoreCLR, V8 and JavaScriptCore; GTK 3, Cairo; OpenGL through GLFW and LWJGL
  • Mach exception handling, keychain, SecureTransport TLS, Objective-C runtime, libunwind, posix_spawn

Not supported: SVE/SME instructions.

Tests: 182 programs compared against native x86_64 builds (./run_tests.sh); in the final run ios_swiftui2_ipa failed once (a SwiftUI slider value read during an animation) and passed in 15 reruns, alone and under CPU load.

Install

  • Rebar-launcher: Rebar.app. Unzip, move to Applications, open. If macOS says the app is damaged: xattr -dr com.apple.quarantine /Applications/Rebar.app.
  • rebar (command line): keep rebar and librebar_exec.dylib together, run ./rebar path/to/arm64/binary [args...].

Build from source: ./build.sh.