Open hanchaoqun opened 2 years ago
I'll submit a fix for this issue soon.
cc @cherrymui
gollvm doesn't work when enable_gc is enabled, since there is no stackmap generated for the runtime functions written in C/C++, and gollvm uses sysv64ABI to generate code, the CSRs are not handled during the unwinding process. I think there's still lots of work to do.
gollvm doesn't work when enable_gc is enabled, since there is no stackmap generated for the runtime functions written in C/C++, and gollvm uses sysv64ABI to generate code, the CSRs are not handled during the unwinding process. I think there's still lots of work to do.
By looking into the code, i think it already has emits the pointer map for Go func, and when GC is triggered by runtime, it can get that infomation from the unwinding process. Yes, you are right, no for C funcs , so C funcs are skipped when unwinding. And I don't see any plans to support GC for C functions.
There is no need for GoLLVM to build stackmaps for C functions. The rules for Go calling into C do not permit Go pointers to live only in C code.
@ianlancetaylor Thanks, how about the pointers lived in the callee saved registers? BTW what's the current status of accurate GC in GoLLVM?
My understanding is that GoLLVM has fully accurate GC. I don't know the details of how callee saved registers are handled. @cherrymui did the implementation.
@cherrymui Hi, could you please spare us some time talking about the status of the accurate GC implementation of GoLLVM. Is it already worked and well tested? We've tried to enable it and run some benchmarks but failed. By looking into the code, I didn't see any code related to handling pointers in the callee saved registers, and the LLVM MC didn't emit the information of this part. The current implementation only emits the stackmap entry, which is a bit vector of live pointers on the stack:
// Stack map entry:
// uint32_t nbits;
// uint8_t *data;
Similar to the go compiler's implementation, but I think there's much differences between these two compilers. The go compiler doesn't have any callee saved registers, and pointers live in the registers are well handled by asyncpreempt(save all registers on stack and scan them conservatively). I don't have much knowledge & background about the GC implementation, please correct me if I missed something. Thanks! cc @ianlancetaylor
@huanglanzhiguan gollvm implement the statepoint pass, which will analyze the live pointers, and then spill the live pointers which across the statepoint into current stack slots.
The fix CL : https://go-review.googlesource.com/c/gollvm/+/407274
The GC implementation worked and was well tested. But I don't test it on a frequent base.
The idea is that for any pointers that are live across a call, the compiler would generate instructions to spill the pointers (or perhaps pointers to the same object) to the stack before the call, so there is always a stack copy which the GC can see. And then the GC doesn't need to look at callee-save registers. It is probably less efficient than scanning callee-save registers, but it was easier to implement.
@cherrymui By the way, if I may ask, what is the reason behind gollvm not utilizing LLVM's stack map?
@MATRIXKOO I'm not sure I understand what you mean by "gollvm not utilizing LLVM's stack map". Gollvm does use LLVM's stack maps feature when -enable-gc is set.
@cherrymui I mean llvm generated stackmap, located in llvm-project/llvm/tools/gollvm/passes/GC.cpp,Someone told me that gollvm don't use llvm stackmap. He/She said, "gollvm don't support stackmap." true?
llvm-project/llvm/tools/gollvm/passes/GC.cpp
This is exactly what gollvm uses.
It is true that gollvm doesn't use the stack map format mentioned in https://llvm.org/docs/StackMaps.html . That format contains much more information than what we need. We use a more compact format.
What version of Go are you using (
go version
)?gollvm master
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
File a.go
compile a.go with
llvm-goc -enable-gc=1 a.go
command.What did you expect to see?
No error, successful build.
What did you see instead?