Design documents for Limelight: a compiled runtime for PHP with a memory-first architecture. PHP source compiles through LLVM to native code; memory is managed by arenas, compiler-tracked ownership, and pluggable garbage collection instead of a one-size-fits-all VM heap.
Status: design phase. These RFCs fix the architecture before the first vertical slice is built. Deferred work lives in BACKLOG.md.
| Pillar | Idea | RFC |
|---|---|---|
| Memory categories | Every object lives in a category: request arena, long-lived, immortal, or GC heap. Most objects die with their arena in O(1) and are invisible to the GC | arenas, arena-reset |
| Static lifetimes | The compiler tracks ownership and moves, Rust-style but with a runtime fallback instead of compile errors. Proven objects get zero refcounting and a scheduled destructor call | static-lifetimes |
| Pluggable GC | The collector is a build-time strategy behind a fixed contract. Default rc-trace: ARC + arenas + stop-the-thread cycle tracing. Flagship against pauses: concurrent SATB marking |
strategies, satb, heap-design |
| Actors | #[Actor] classes own their arenas and execute serially; queues are the only door between actors. Collection runs per actor at message boundaries; each actor may bind its own GC |
actors |
| Object model | C++-grade dispatch for PHP: inline-trailing vtables, COM-style itables, fat interface references, inline caches that never invalidate | classes, lowering, caches |
| Exceptions | Three channels — table-driven unwinding, an error-return channel, and a non-catchable bailout for fatals — with the compiler choosing, not the programmer. The return channel is also the portability floor: it needs no host support, which is what makes the embedded/WASM/JVM modes possible. Design has known open defects, listed in the document | exceptions |
| Values | 16-byte ValueBox for the dynamic world, raw unboxed slots for declared types, COW as a per-object flag | values, strings, arrays |
- values.md — ValueBox/unboxed contracts, Optional,
UNINIT, COW protocol - strings.md — string layout, string-as-class, interpolated template class
- arrays.md — one
arrayclass, three storage strategies - arrays-hashtable.md — the ordered hash: entry layout, index, deletion, flood defence
- classes.md — object layout, class descriptors, vtables, itables, property access
- lowering.md — the C structures and LLVM IR behind the model
- caches.md — every cache site, why none carries a replacement policy, and what each does when it fills
- model/memory/ — arenas, arena reset, static lifetimes, ARC optimizations
- model/gc/ — GC strategies, SATB, heap design, research survey
- implementation-language.md — Rust core + thin C++ LLVM layer
- object-lifecycle.md —
newand the three-phase teardown - actors.md — actor contexts, message queues, per-actor GC
- exceptions.md —
throw/try/finally: two error channels, trace materialization, and whytrycosts nothing
- interop/ — IR-level interop with C++/Rust (research)
- io/, stdlib/ — placeholders, not yet designed
- attributes.md — the attributes principle (root document)
- BACKLOG.md — deferred work, collected from all RFCs
Attributes are the language surface. Limelight
adds zero new keywords and zero new syntax to PHP. Every capability
(actors, GC hints, generics) enters through native PHP 8 attributes
under the Limelight\ namespace, and the compiler's whole-program
analysis materializes its findings back into source as the same
attributes. A Limelight program is, syntactically, a valid PHP program.
New to the project? Read in this order:
- attributes.md — the principle everything hangs on
- model/memory/arenas.md — memory categories, the core bet
- model/gc/strategies.md — how collection is organized
- model/values.md and model/classes.md — what a value and an object are
- runtime/actors.md — the concurrency story