-
Notifications
You must be signed in to change notification settings - Fork 46
Implement register-based closure ctx #1568
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Note The number of changes in this pull request is too large for Gemini Code Assist to generate a summary. |
387a4f1 to
b39916b
Compare
Code Review SummaryThis PR implements a well-designed register-based closure context mechanism. The architecture is sound with appropriate register selection (callee-saved registers), proper save/restore semantics, and comprehensive test coverage. Strengths:
Minor Issues to Address:
Overall, this is a solid implementation ready for merge after addressing minor issues. |
| // Test scenario: calling another closure before reading free variables | ||
| // This may cause x26 register to be clobbered | ||
|
|
||
| func noop() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This noop() function is declared but never used in the test file. Consider either removing it or adding a test case that uses it (e.g., a noop call between closure operations to test register preservation across non-closure calls).
| // go with interface method value | ||
| im := i.Add | ||
| go im(8) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency with defer/in.go, consider adding direct method call tests:
// go with direct method call (not via method value)
go s.Add(7)
go sv.Inc(8)The defer test includes these (lines 63-64), so having parity would ensure the go statement handles direct method calls the same way.
92e598c to
26e9b99
Compare
26e9b99 to
b866d12
Compare
- Fix crosscompile.use() to set LLVMTarget/GOOS/GOARCH for non-wasm cross-compilation - Add unified compiler(compilingCSource bool) method that handles --target flag - Add NativeCCompile flag to compile C files for host OS during cross-compilation - Clone flag slices in compiler() to prevent side effects - Remove redundant targetArgs(), cTargetArgs(), cCompiler() methods - Enable NativeCCompile in cabi tests to avoid sysroot issues on Darwin This fixes TestBuild failures when cross-compiling from Darwin to Linux.
Add aliases for common LLVM target triple arch names: - x86_64 -> amd64 - aarch64 -> arm64 - armv5/armv6/armv7 -> arm - i386/i686 -> 386 - wasm32 -> wasm This fixes TestABI failures where llgo was not applying cabi type transformations because arch names from LLVM target triples (e.g. x86_64-unknown-linux-gnu, armv7-unknown-linux) were not matched in the switch statement.
- Add target_arch.go with getCanonicalArchName helper for normalizing arch names - Update ctxreg.go to export ReserveFlags for cross-compilation register handling - Update ssa/expr.go and ssa_test.go for related changes
- Fix explicitTargetTriple to detect cross-compilation by GOOS/GOARCH - Add NativeCCompile documentation (only for cabi_test) - Restore TestRun* tests and add TestFromTestcall - Add filterLinkerWarnings to filter ld64.lld warnings in test output - Add expect.txt.new to .gitignore - Fix import alias (envllvm -> llvm)
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1568 +/- ##
==========================================
- Coverage 91.01% 89.66% -1.36%
==========================================
Files 45 46 +1
Lines 11971 12213 +242
==========================================
+ Hits 10896 10951 +55
- Misses 899 1075 +176
- Partials 176 187 +11 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
In the new register-based closure ABI, context is passed via register, not as a function parameter. The reflect.Value.call was incorrectly prepending the context pointer to the FFI argument list when calling closures, causing argument misalignment and nil pointer dereference. Fixes text/template println error when executing templates.
Map riscv32 to riscv64 in goarchFromTriple so ESP32-C3 and other RISC-V 32-bit targets can use the x27 context register instead of falling back to global variable.
Remove leading unsafe.Pointer parameter from MakeFunc FFI signature and update argument indexing to match the new register-based closure calling convention. All closures now use register-based context instead of passing context as a function parameter. Fixes texttemplate and reflectmake demos.
Fix single-element struct handling for riscv32 ABI by properly flattening pointer and i32 types to i32, and float types to float on ilp32f/ilp32d ABIs. This fixes TestABI failures for esp32c3, riscv32_ilp32, riscv32_ilp32f, and riscv32_ilp32d targets.
Summary
This PR implements a register-based closure context (ctx) mechanism to significantly improve closure call performance by avoiding TLS/global memory access when possible. This addresses issue #1497.
Background
Previously, closure contexts were passed exclusively through a global or TLS slot, which required memory loads on every closure call. This approach worked but had performance overhead and potential thread-safety issues in certain scenarios.
Changes
Core Implementation
Architecture-Specific Reserved Registers
Closure Representation
{fn: *func, data: unsafe.Pointer}layoutfn: original Go signature (no explicit ctx parameter)data: nil for plain functions, heap-allocated context for free variablesCalling Convention
write_ctx(data)- writes to reserved register or fallbackrestore_ctx()- restores previous ctx to avoid corrupting callerRegister Preservation
-ffixed-*flags to clang to prevent LLVM register allocation from clobbering the ctx registernative use()andUseTarget()pathsWrapper Functions
__llgo_stub.<fn>$ctx__llgo_stub._llgo_func$<hash>Test Coverage
Added comprehensive test cases in
cl/_testgo/andcl/_testcall/:sync.Once.Dopatterns)Documentation
Updated
doc/closure.mdwith:Performance Impact
Testing
All existing tests pass. New test cases specifically validate:
Issue References
Fixes #1497