defer: enable loop lowering
This commit is contained in:
32
doc/defer-tls-gc.md
Normal file
32
doc/defer-tls-gc.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Defer Loop GC Integration
|
||||
|
||||
## Background
|
||||
|
||||
`defer` chains are stored in a per-thread TLS slot so that unwind paths can locate the active `*runtime.Defer`. With the default allocator (`AllocU`) backed by Boehm GC (bdwgc), those TLS-resident pointers were invisible to the collector. In stress scenarios—e.g. `TestDeferLoopStress` with 1,000,000 defers—the collector reclaimed the defer nodes, leaving dangling pointers and causing crashes inside the deferred closures.
|
||||
|
||||
Prior experiments (`test-defer-dont-free` branch) confirmed the crash disappeared when allocations bypassed GC (plain `malloc` without `free`), pointing to a root-registration gap rather than logical corruption.
|
||||
|
||||
## Solution Overview
|
||||
|
||||
1. **GC-aware TLS slot helper** *(from PR [#1347](https://github.com/goplus/llgo/pull/1347))*
|
||||
- Added `runtime/internal/clite/tls`, which exposes `tls.Alloc` to create per-thread storage that is automatically registered as a Boehm GC root.
|
||||
- `SetThreadDefer` delegates to this helper so every thread reuses the same GC-safe slot without bespoke plumbing.
|
||||
- The package handles TLS key creation, root registration/removal, and invokes an optional destructor when a thread exits.
|
||||
|
||||
2. **SSA codegen synchronization**
|
||||
- `ssa/eh.go` now calls `runtime.SetThreadDefer` whenever it updates the TLS pointer (on first allocation and when restoring the previous link during unwind).
|
||||
- Defer argument nodes and the `runtime.Defer` struct itself are allocated with `aggregateAllocU`, ensuring new memory comes from GC-managed heaps, and nodes are released via `runtime.FreeDeferNode`.
|
||||
|
||||
3. **Non-GC builds**
|
||||
- The `tls` helper falls back to a malloc-backed TLS slot without GC registration, while `FreeDeferNode` continues to release nodes via `c.Free` when building with `-tags nogc`.
|
||||
|
||||
## Testing
|
||||
|
||||
Run the stress and regression suites to validate the integration:
|
||||
|
||||
```sh
|
||||
./llgo.sh test ./test -run TestDeferLoopStress
|
||||
./llgo.sh test ./test
|
||||
```
|
||||
|
||||
The updated `TestDeferLoopStress` now asserts 1,000,000 loop defers execute without failure, catching regressions in GC root tracking.
|
||||
Reference in New Issue
Block a user