docs: update documentation with RC implementation status
- C_BACKEND.md: Update memory management from "Leaks" to "Scope-based RC", update comparison tables with Koka/Rust/Zig/Go - LANGUAGE_COMPARISON.md: Add status column to gap tables, add RC row - OVERVIEW.md: Add C backend RC to completed features, update limitations - REFERENCE_COUNTING.md: Add "Path to Koka/Rust Parity" section with: - What we have vs what Koka/Rust have - Remaining work for full memory safety (~230 lines) - Performance optimizations for Koka parity (~600 lines) - Cycle detection strategy Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -363,7 +363,114 @@ void lux_check_leaks() {
|
||||
|
||||
---
|
||||
|
||||
## Path to Koka/Rust Parity
|
||||
|
||||
### What We Have Now (Basic RC)
|
||||
|
||||
Our current implementation provides:
|
||||
- **Deterministic cleanup** - Memory freed at predictable points (scope exit)
|
||||
- **No GC pauses** - Unlike Go/Java, latency is predictable
|
||||
- **Leak detection** - Debug mode catches memory leaks during development
|
||||
- **No manual management** - Unlike C/Zig, programmer doesn't call free()
|
||||
|
||||
### What Koka Has (Perceus RC)
|
||||
|
||||
Koka's Perceus system adds several optimizations we don't have:
|
||||
|
||||
| Feature | Description | Benefit | Complexity |
|
||||
|---------|-------------|---------|------------|
|
||||
| **Last-use analysis** | Detect when a variable's final use allows ownership transfer | Avoid unnecessary copies | Medium |
|
||||
| **Reuse (FBIP)** | When rc=1, mutate in-place instead of copy | Major performance boost | High |
|
||||
| **Drop specialization** | Generate type-specific drop instead of polymorphic | Fewer branches, faster | Low |
|
||||
| **Drop fusion** | Combine multiple consecutive drops | Fewer function calls | Medium |
|
||||
| **Borrow inference** | Avoid incref when borrowing temporaries | Reduce RC overhead | High |
|
||||
|
||||
### What Rust Has (Ownership)
|
||||
|
||||
Rust's ownership system is fundamentally different:
|
||||
|
||||
| Aspect | Rust | Lux RC | Tradeoff |
|
||||
|--------|------|--------|----------|
|
||||
| **When checked** | Compile-time | Runtime | Rust catches bugs earlier |
|
||||
| **Runtime cost** | Zero | RC operations | Rust is faster |
|
||||
| **Learning curve** | Steep (borrow checker) | Gentle | Lux is easier to learn |
|
||||
| **Expressiveness** | Limited by lifetimes | Unrestricted | Lux is more flexible |
|
||||
| **Cycles** | Prevented by design | Would leak | Rust handles more patterns |
|
||||
|
||||
**Key insight:** We can never match Rust's zero-overhead guarantees because ownership is checked at compile time. RC always has runtime cost. But we can be as good as Koka.
|
||||
|
||||
### Remaining Work for Full Memory Safety
|
||||
|
||||
#### Phase A: Complete Coverage (Prevent All Leaks)
|
||||
|
||||
1. **Closure RC** - Environments should be RC-managed
|
||||
- Allocate env with `lux_rc_alloc`
|
||||
- Drop env when closure is dropped
|
||||
- ~50 lines in `emit_lambda`
|
||||
|
||||
2. **ADT RC** - Algebraic data types with heap fields
|
||||
- Track which variants contain RC fields
|
||||
- Generate drop functions for each ADT
|
||||
- ~100 lines
|
||||
|
||||
3. **Early return handling** - Cleanup all scopes on return
|
||||
- Current impl handles simple cases
|
||||
- Need nested scope cleanup
|
||||
- ~30 lines
|
||||
|
||||
4. **Complex conditionals** - If/else creating RC values
|
||||
- Switch from ternary to if-statements
|
||||
- Track RC creation in branches
|
||||
- ~50 lines
|
||||
|
||||
#### Phase B: Performance Optimizations (Match Koka)
|
||||
|
||||
1. **Last-use optimization**
|
||||
- Track variable liveness
|
||||
- Skip incref on last use (transfer ownership)
|
||||
- Requires dataflow analysis
|
||||
- ~200 lines
|
||||
|
||||
2. **Reuse analysis (FBIP)**
|
||||
- Detect `rc=1` at update sites
|
||||
- Mutate in-place instead of copy
|
||||
- Major change to list operations
|
||||
- ~300 lines
|
||||
|
||||
3. **Drop specialization**
|
||||
- Generate per-type drop functions
|
||||
- Eliminate polymorphic dispatch
|
||||
- ~100 lines
|
||||
|
||||
### Estimated Effort
|
||||
|
||||
| Phase | Description | Lines | Priority |
|
||||
|-------|-------------|-------|----------|
|
||||
| A1 | Closure RC | ~50 | P0 - Closures leak |
|
||||
| A2 | ADT RC | ~100 | P1 - ADTs leak |
|
||||
| A3 | Early returns | ~30 | P1 - Edge cases |
|
||||
| A4 | Conditionals | ~50 | P2 - Uncommon |
|
||||
| B1 | Last-use opt | ~200 | P3 - Performance |
|
||||
| B2 | Reuse (FBIP) | ~300 | P3 - Performance |
|
||||
| B3 | Drop special | ~100 | P3 - Performance |
|
||||
|
||||
**Phase A total: ~230 lines** - Gets us to "no leaks"
|
||||
**Phase B total: ~600 lines** - Gets us to Koka-level performance
|
||||
|
||||
### Cycle Detection
|
||||
|
||||
RC cannot handle cycles (A → B → A). Options:
|
||||
|
||||
1. **Ignore** - Cycles are rare in functional code (our current approach)
|
||||
2. **Weak references** - Programmer marks back-edges
|
||||
3. **Cycle collector** - Periodic scan for cycles (adds GC-like pauses)
|
||||
|
||||
Koka also ignores cycles, relying on functional programming's natural acyclicity.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [Perceus Paper](https://www.microsoft.com/en-us/research/publication/perceus-garbage-free-reference-counting-with-reuse/)
|
||||
- [Koka Reference Counting](https://koka-lang.github.io/koka/doc/book.html)
|
||||
- [Rust Ownership](https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html)
|
||||
|
||||
Reference in New Issue
Block a user